Pemilihan Proyek

Menetapkan lingkup yang melatih konkurensi dan HTTP.

Daftar isi

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.

KandidatBeban konkurensiPeran HTTPPenilaian
Perayap situstinggiclientBergantung pada situs luar, sehingga keluaran dan pengujian sulit direproduksi
Aplikasi percakapantinggiserverMenuntut koneksi bertahan lama dan pengelolaan sesi yang melampaui lingkup
Layanan statistik tekssedangserverMasukan 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.

text Bentuk tubuh permintaan
{"potongan": ["satu dua tiga", "empat lima"]}
text Bentuk tubuh respons
{"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.

FieldArtiAturan
jumlah_katabanyaknya katakata adalah rangkaian karakter yang dipisahkan spasi putih
jumlah_karakterpanjang potongandihitung dalam rune, spasi ikut dihitung
kata_terpanjangkata dengan rune terbanyakapabila ada yang sama panjang, kata yang muncul lebih dahulu yang dipilih
durasi_bacaestimasi lama membacadihitung 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.

go statistik.go
// 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)
}
text Keluaran
11 kata, 89 karakter, terpanjang "Pemrograman", durasi baca 3.3 detik

Fungsi 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 Analisis di atas.
  • Menghitung karakter dengan len pada string. Fungsi len menghitung byte, sehingga huruf seperti é yang tersusun atas dua byte terhitung dua karakter. Perbaikannya, hitung dengan utf8.RuneCountInString sebagaimana 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, dan gofmt.
  • Aturan analisis ditegakkan lewat fungsi Analisis yang sudah dapat dijalankan sejak awal proyek.

Referensi#