Seluruh modul ini mengerjakan satu proyek latihan utuh yang menyatukan dua kemampuan inti jalur ini, yaitu konkurensi dan HTTP. Topik ini menetapkan proyek dan lingkupnya, yaitu layanan statistik teks berbasis HTTP dengan pekerja konkuren, lengkap dengan kontrak layanan, aturan analisis, dan kriteria selesai. Setelah topik ini dibaca, setiap keputusan teknis selanjutnya memiliki rujukan tertulis yang ditetapkan lebih dahulu.
Memilih lingkup proyek#
Sebuah proyek latihan memberi manfaat penuh apabila lingkupnya melatih kemampuan yang sudah dipelajari sekaligus masih dapat diselesaikan dalam beberapa sesi kerja. Tiga kriteria mempersempit pilihan. Pertama, pekerjaan intinya harus dapat dipecah menjadi unit-unit kecil yang saling bebas, karena bentuk itulah yang paling alami dikerjakan sekelompok pekerja konkuren. Kedua, proyeknya harus memiliki antarmuka HTTP yang jelas, karena paket net/http baru bermakna ketika dipraktikkan pada layanan yang benar-benar menerima permintaan. Ketiga, lingkupnya harus cukup kecil agar dapat diuji menyeluruh, karena proyek yang tidak selesai tidak menguji apa pun.
Tiga kandidat diuji terhadap kriteria tersebut.
| Kandidat | Beban konkurensi | Peran HTTP | Penilaian |
|---|---|---|---|
| Perayap situs | tinggi | client | Bergantung pada situs luar, sehingga keluaran dan pengujian sulit direproduksi |
| Aplikasi percakapan | tinggi | server | Menuntut koneksi bertahan lama dan pengelolaan sesi yang melampaui lingkup |
| Layanan statistik teks | sedang | server | Masukan berupa teks murni, sehingga seluruh perilakunya dapat diuji secara deterministik |
Layanan statistik teks terpilih. Layanan ini menerima potongan teks, menghitung statistiknya secara konkuren, lalu menyerahkan hasilnya sebagai JSON. Seluruh masukannya berasal dari permintaan itu sendiri, tanpa basis data dan tanpa layanan luar, sehingga setiap pengujian dapat diulang dengan hasil yang sama. Beban konkurensinya juga nyata, karena satu permintaan dapat membawa banyak potongan sekaligus dan seluruh potongan itu boleh dianalisis bersamaan.
Kontrak layanan dan batasannya#
Kontrak layanan dituliskan sebelum kode pertama dibuat, karena kontrak itulah yang mengikat seluruh keputusan berikutnya. Layanan menyediakan satu endpoint, yaitu POST /statistik. Permintaan berupa JSON dengan satu field potongan berbentuk daftar string. Respons berupa JSON dengan satu field hasil berupa daftar statistik yang urutannya sama dengan urutan potongan pada permintaan. Bentuk keduanya pada contoh dua potongan sebagaimana berikut.
{"potongan": ["satu dua tiga", "empat lima"]}{"hasil":[{"jumlah_kata":3,"jumlah_karakter":13,"kata_terpanjang":"satu","durasi_baca":"0.9 detik"},{"jumlah_kata":2,"jumlah_karakter":10,"kata_terpanjang":"empat","durasi_baca":"0.6 detik"}]}Setiap field pada hasil memiliki aturan yang tetap.
| Field | Arti | Aturan |
|---|---|---|
jumlah_kata | banyaknya kata | kata adalah rangkaian karakter yang dipisahkan spasi putih |
jumlah_karakter | panjang potongan | dihitung dalam rune, spasi ikut dihitung |
kata_terpanjang | kata dengan rune terbanyak | apabila ada yang sama panjang, kata yang muncul lebih dahulu yang dipilih |
durasi_baca | estimasi lama membaca | dihitung dari asumsi 200 kata per menit, ditulis dengan satu desimal |
Batas permintaannya dirinci juga, karena kontrak yang baik menyebutkan penolakannya. Permintaan dengan tubuh bukan JSON yang sah ditolak dengan status 400, begitu pula permintaan tanpa potongan. Permintaan dengan lebih dari seratus potongan ditolak dengan status 413, dan metode selain POST ditolak dengan status 405 oleh mux.
Daftar hal yang berada di luar lingkup sama pentingnya dengan batas di atas. Proyek ini tidak menyimpan hasilnya secara permanen, tidak mengenali pengguna, tidak memakai framework HTTP pihak ketiga, dan tidak membahas penyetelan untuk lalu lintas besar. Setiap butir yang dikeluarkan dari lingkup hari ini dapat menjadi proyek latihan tersendiri nanti, sedangkan yang dibiarkan samar akan menumpuk sebagai pekerjaan tak berujung.
Kriteria selesainya juga ditetapkan sekarang, dan kriterianya berupa perintah, bukan perasaan. Proyek dinyatakan selesai apabila go test lolos pada seluruh paket, go test -race tidak menemukan laporan race, benchmark worker pool tercatat, serta go vet dan gofmt bersih. Perintah-perintah itu dijalankan sebagai penutup pengerjaan proyek.
Menetapkan aturan analisis dalam kode#
Aturan pada tabel di atas langsung diturunkan menjadi program kecil yang dapat dijalankan. Menetapkan aturan dalam kode sejak awal membuang ambiguitas, karena setiap kalimat kontrak yang samar akan terlihat pada keluarannya. Program berikut memuat fungsi Analisis beserta contoh pemanggilannya pada satu potongan tetap.
// Program statistik.go menetapkan aturan analisis satu potongan teks
// sebelum lingkup proyek dirinci lebih jauh.
package main
import (
"fmt"
"strings"
"unicode/utf8"
)
// Statistik menyimpan hasil analisis satu potongan teks.
type Statistik struct {
JumlahKata int
JumlahKarakter int
KataTerpanjang string
DurasiBaca string
}
// kataPerMenit adalah asumsi kecepatan baca untuk estimasi durasi.
const kataPerMenit = 200
// Analisis menghitung statistik satu potongan teks.
func Analisis(potongan string) Statistik {
kata := strings.Fields(potongan)
terpanjang := ""
for _, k := range kata {
if utf8.RuneCountInString(k) > utf8.RuneCountInString(terpanjang) {
terpanjang = k
}
}
detik := float64(len(kata)) / kataPerMenit * 60
return Statistik{
JumlahKata: len(kata),
JumlahKarakter: utf8.RuneCountInString(potongan),
KataTerpanjang: terpanjang,
DurasiBaca: fmt.Sprintf("%.1f detik", detik),
}
}
func main() {
teks := "Pemrograman konkuren membagi pekerjaan menjadi unit kecil yang dapat dijalankan bersamaan"
s := Analisis(teks)
fmt.Printf("%d kata, %d karakter, terpanjang %q, durasi baca %s\n", s.JumlahKata, s.JumlahKarakter, s.KataTerpanjang, s.DurasiBaca)
}11 kata, 89 karakter, terpanjang "Pemrograman", durasi baca 3.3 detikFungsi Analisis memetakan setiap aturan kontrak ke satu baris kode. Pemisahan kata diserahkan kepada strings.Fields, sehingga spasi berlebih tidak menghasilkan kata kosong. Penghitungan karakter memakai utf8.RuneCountInString, bukan len, karena potongan dapat memuat huruf yang tersusun atas lebih dari satu byte. Pemilihan kata terpanjang memakai perbandingan > yang ketat, sehingga kata yang datang lebih dahulu menang apabila sama panjangnya. Estimasi durasi mengonversi banyaknya kata menjadi detik menurut kataPerMenit, lalu memformatnya dengan satu desimal.
Fungsi main pada program ini hanya peraga yang memanggil Analisis sekali dengan teks tetap, sehingga keluarannya dapat diperiksa ulang kapan pun. Bentuk fungsi inilah yang nantinya dipindahkan menjadi paket teks, sedangkan statistiknya menjadi isi respons JSON pada kontrak di atas. Lingkup proyek pun berdiri di atas tiga hal yang sudah tertulis, yaitu kontrak HTTP, aturan per field, dan kode yang membuktikan aturan itu.
Kesalahan umum#
- Memperbesar lingkup sebelum kriteria selesai tercapai. Fitur tambahan seperti penghitungan frekuensi kata terdengar kecil, tetapi menyisipkan pekerjaan baru di tengah kontrak yang sedang dibangun menunda penyelesaian proyek. Perbaikannya, catat ide itu sebagai kandidat lingkup tersendiri dan tuntaskan kriteria yang ada lebih dahulu.
- Membiarkan aturan analisis hanya berupa kalimat. Frasa seperti “kata yang panjang” tanpa definisi menghasilkan dua implementasi yang berbeda padahal sama-sama merasa benar. Perbaikannya, turunkan setiap aturan menjadi fungsi yang keluarannya dapat dibandingkan, sebagaimana
Analisisdi atas. - Menghitung karakter dengan
lenpada string. Fungsilenmenghitung byte, sehingga huruf sepertiéyang tersusun atas dua byte terhitung dua karakter. Perbaikannya, hitung denganutf8.RuneCountInStringsebagaimana ditetapkan kontrak.
Ringkasan#
- Proyek latihan yang dipilih adalah layanan statistik teks berbasis HTTP dengan pekerja konkuren, karena lingkupnya melatih keduanya dan seluruh perilakunya dapat diuji secara deterministik.
- Kontrak layanan ditetapkan lebih dahulu, mencakup endpoint, bentuk JSON, status penolakan, batas seratus potongan, dan aturan tiap field.
- Kriteria selesai berupa perintah yang konkret, yaitu
go test,go test -race, benchmark,go vet, dangofmt. - Aturan analisis ditegakkan lewat fungsi
Analisisyang sudah dapat dijalankan sejak awal proyek.
Referensi#
- Effective Go — The Go Authors — Gaya dan konvensi bahasa Go yang menjadi acuan penulisan seluruh program proyek ini.
- Package net/http — The Go Authors — Dokumentasi paket yang menjadi dasar lapisan HTTP pada proyek.