Membangun Chat Service sebagai Backend Developer Intern di Come

--

Pertama-tama ini bukanlah tutorial untuk membangun chat service menggunakan Golang, ini adalah cerita pengalaman saya menyelesaikan tugas magang di Come. Pada awal bulan Maret lalu, saya mengikuti program remote internship yang diadakan oleh Come (PT Global Teknokreasi Indonesia). Program tersebut berjalan selama tiga bulan. Sebagai backend developer intern, salah satu tugas yang harus saya selesaikan adalah membangun chat service dengan Golang, di-dockerize, lalu di-deploy ke AWS. Mari kita bahas apa saja yang saya gunakan selama membangun chat service.

Kudos to MariaLetta yang membuat berbagai ilustrasi Golang

Golang

Go atau Golang adalah bahasa open-source yang dirancang di Google oleh Robert Griesemer, Rob Pike, dan Ken Thompson. Go sendiri dibangun dengan berfokus pada kesederhanaan bahasa, skalabilitas, kecepatan, dan juga keandalan.

Lalu mengapa Golang ?

  • Go adalah bahasa statis yang di-compile.
  • Dibangun dengan mendukung model concurrency dengan GoRoutines.
  • Memiliki garbage collector.
  • Syntax yang lebih ringkas dibandingkan bahasa lain.

Keunggulan-keunggulan tersebut lah yang membuat Come memilih untuk membangun sistem mereka menggunakan Golang. Ditambah dengan banyaknya standard library dan third party library membuat mengembangkan sistem dengan Golang menjadi lebih mudah. Dua dari beberapa library yang saya gunakan dalam proses pengembangan chat service adalah Echo dan GORM.

Echo

Echo adalah suatu open-source Go web application framework. Golang telah menyediakan ‘net/http’ standard library untuk membuat web application, namun sebuah aplikasi mungkin membutuhkan fitur yang tidak dimiliki oleh standard library. Ada banyak framework yang memiliki fitur lebih dari standard library tersedia bagi Go, namun Echo memiliki performa yang paling baik diantara pesaing-pesaing nya.

Fast and unfancy HTTP server framework for Go (Golang). Up to 10x faster than the rest.

-Echo

Perbandingan waktu respon antara Echo dan Gin

Echo tidak memberikan batasan terhadap design pattern dan struktur aplikasi yang dibangun. Developer dibebaskan untuk menerapkan design pattern apapun sesuai dengan preferensi mereka. Maka dari itu sebelum menggunakan Echo lebih baik untuk mengenal satu atau beberapa design pattern terlebih dahulu. Pada pengembangan chat service ini, saya menerapkan Standard Package Layout sebagai design pattern, selebihnya akan dibahas setelah membahas GORM.

GORM

GORM adalah suatu framework object-relational mapping untuk relational database. GORM mempermudah proses mapping dari model ke database. GORM dibuat untuk mempermudah developer dalam menggunakan relational database. GORM dibagun diatas standard library ‘database/sql’.

Gambaran dari fitur yang disediakan oleh GORM antara lain adalah :

  • Full-Featured ORM (hampir)
  • Associations (Has One, Has Many, Belongs To, Many To Many, Polymorphism)
  • Hooks (Before/After Create/Save/Update/Delete/Find)
  • Preloading (eager loading)
  • Transactions
  • Composite Primary Key
  • SQL Builder
  • Auto Migrations
  • Logger
  • Extendable, write Plugins based on GORM callbacks
  • Every feature comes with tests
  • Developer Friendly

Standard Package Layout

Standard Package Layout merupakan suatu design pattern untuk Golang yang dibuat oleh Ben Johnson. Setiap projek Golang yang pernah ia kerjakan memiliki pattern yang berbeda-beda, dan tidak semua pattern tersebut dirancang dengan baik. Menurut Ben Johnson diperlukan standar yang lebih baik untuk desain aplikasi Golang. Maka dari itu Ben Johnson mengusulkan suatu pattern yang akan membantu dalam mengurai keterikatan code, mempermudah dalam melakukan pengujian, dan memberikan konsistensi pada projek yang sedang di bangun.

Terdapat empat prinsip dalam menerapkan Standard Package Layout, yaitu :

  1. Root package untuk domain types

Root package berisi logical, high-level language yang mendeskripsikan bagaimana data dan proses saling berinteraksi. Package ini disimpan dalam folder internal dan akan berbentuk kurang lebih seperti ini

package model
// Message Domain Modeltype Message struct { Base ChannelID uint `json:"channel_id" gorm:"not null"` UserID uint `json:"user_id" gorm:"not null"` Message string `json:"message" gorm:"type:text"` ReadBy string `json:"read_by" gorm:"type:text"` IsRemoved bool `json:"is_removed" gorm:"DEFAULT:FALSE"`}// Interface for MessageDBtype MessageDB interface { Create(*Message) (*Message, error) ListByChannelID(uint, int, int) ([]*Message, error) Update(uint, *Message) (*Message, error) ViewById(uint) (*Message, error)}

2. Kelompokkan subpackage berdasarkan dependency

Pada root package tidak boleh bergantung kepada external dependency, maka dari itu dependency tersebut kita masukkan ke dalam subpackage. Contohnya MessageDB akan diimplementasikan menggunakan MySQL, maka kita bisa membuat package MySQL yang berisi implementasi dari MessageDB. Bentuknya kurang lebih akan seperti ini

package mysql// MessageDB Modeltype MessageDB struct {    cl *gorm.DB}// Create new MessageDB valuefunc NewMessageDB(db *gorm.DB) *MessageDB {    return &MessageDB{cl:db}}// MySQL implementation for getting message detail by idfunc (mdb *MessageDB) ViewById(id uint) (*model.Message, error) {    var msg model.Message    if err := mdb.cl.Find(&msg, id).Error; err != nil && err == gorm.ErrRecordNotFound {        return nil, model.ErrMessageNotFound    } else if err != nil {        return nil, err    }    return &msg, nil}
...

3. Menggunakan shared mock subpackage

Karena dependency diisolasi dari dependency lain oleh domain interface, maka kita bisa menggunakannya untuk meng-inject mock implementation kita. Namun pada pengembangan chat service ini kita tidak akan melakukan testing dan membuat mock implementation.

4. Main package mengikat dependency lain

Kita telah membuat banyak dependency package yang tersebar dimana-mana. Tugas dari main package adalah menyatukan dependency-dependency tersebut.

Untuk menjalankan chat service yang telah dibuat, maka kita perlu menjalankan perintah berikut

$ go run cmd/api/main.go

Setelah proses development selesai, masuklah ke tahap production. Chat service akan di-deploy menggunakan layanan Amazon Web Service. Untuk melakukan itu, maka dibutuhkan untuk meng-install Go dan MySQL di server. Ada cara lain untuk melakukan deploy tanpa harus meng-install Go dan MySQL secara manual di server, yaitu dengan menggunakan Docker.

Docker

Docker adalah serangkaian produk platform as a service (PaaS) yang digunakan untuk menjalankan aplikasi yang telah di containerized. Container sendiri merupakan perangkat lunak yang membungkus code dan segala dependencies dari suatu aplikasi agar dapat dijalankan secara baik dan cepat dari suatu environment ke environment lainnya.

Untuk melakukan containerized pada chat service, maka perlu membuat custom image dengan membuat Dockerfile. Dockerfile adalah sebuah file text yang berisi perintah untuk membangun suatu image. Pada kasus ini Dockerfile nya akan berbentuk seperti ini

FROM golang:1.13WORKDIR /appCOPY . /appRUN go build ./...RUN chmod +x /app/docker-entrypoint.shENV COME_RUN_MIGRATION=1ENTRYPOINT /app/docker-entrypoint.sh

Ini sedikit penjelasannya :

  • FROM digunakan untuk memberitahu image dasar yang akan digunakan untuk membangun custom image. Chat service yang dibangun membutuhkan golang versi 1.13 untuk bisa berjalan.
  • WORKDIR digunakan untuk berpindah direktori, sama seperti perintah “$ cd”.
  • COPY digunakan untuk men-copy file dari projek ke image.
  • RUN digunakan untuk menjalankan suatu perintah.
  • ENV digunakan untuk membuat environment variable.
  • ENTRYPOINT digunakan untuk mendefinisikan file yang berisi perintah yang akan dijalankan ketika container dijalankan.

Setelah itu Dockerfile perlu di build dengan cara menjalankan perintah

docker build . -t come-chat-service

Dan yang terakhir menjalankan container dengan perintah

docker container run -p 8080:8080 --name come-chat-service come-chat-service

Rangkuman

  • Golang merupakan bahasa open-source yang didesain di Google oleh orang-orang hebat di bidang ilmu komputer, yang membuat golang menjadi bahasa yang sederhana, memiliki skalabilitas tinggi, cepat dan dapat diandalkan.
  • Echo dan GORM digunakan untuk mempermudah pengembangan chat service dengan fitur-fitur yang mereka miliki. Dan Standard Package Layout membuat aplikasi yang dikembangkan tetap terstruktur dan tidak terikat antar modul.
  • Untuk mempermudah tahapan production, Docker dapat dimanfaatkan untuk melakukan containerized aplikasi sehingga aplikasi dapat berjalan dengan baik di local maupun di server.

--

--