tutorial

47 Reserved Fields dan Reserved Numbers

Dalam dunia rekayasa perangkat lunak, terutama pada pengembangan protokol komunikasi, serialisasi data, dan desain API, istilah reserved fields dan reserved numbers sering kali kita jumpai. Meski sepintas terdengar seperti “mengosongkan slot” tanpa fungsi nyata, keduanya memainkan peran strategis dalam menjaga kompatibilitas dan evolusi sistem.

Artikel ini akan membedah konsep reserved fields dan reserved numbers secara mendalam—dilengkapi dengan contoh kode, simulasi sederhana, serta diskusi strateginya dalam software engineering profesional.


1. Apa Itu Reserved Fields dan Reserved Numbers?

Reserved Fields

Reserved fields adalah bagian dari struktur data (paket, pesan, struct, dsb.) yang dilewati alias disisihkan untuk digunakan di masa depan. Field ini tidak memiliki makna saat ini, harus diabaikan oleh penerima, tetapi tetap dipertahankan dalam struktur.

Contoh situasi:

  • Protokol baru akan lahir, tapi desainnya diduga bakal berkembang.
  • Perubahan (extend) ingin dilakukan tanpa memecah kompatibilitas (backward/forward compatible).

Reserved Numbers

Reserved numbers adalah nilai/angka tertentu dalam field (umumnya enumerasi atau tipe pesan) yang dicadangkan—tidak digunakan sekarang, namun akan diperuntukkan pada revisi mendatang.
Dapat juga bermakna: angka tertentu tidak boleh digunakan oleh implementasi custom (reserved for internal use).


2. Mengapa Reserved Fields dan Numbers Penting?

Berikut tabel ringkas alasan penggunaan keduanya:

TujuanReserved FieldsReserved Numbers
Compatibility✔︎✔︎
Future-proofing✔︎✔︎
Menghindari konflik✔︎
Mempercepat revisi✔︎✔︎

  • Compatibility: Agar sistem baru dan lama bisa tetap ‘bicara’.
  • Future-proofing: Memastikan struktur/protokol tetap relevan setelah bertahun-tahun.
  • Menghindari konflik: Pada assigned enum/ID tertentu, reserved numbers mencegah duplikasi makna antar implementasi.
  • Mempercepat revisi: Memungkinkan penambahan fitur tanpa mengubah seluruh sistem.

3. Contoh Konkret: Reserved Fields pada Protokol

Mari ilustrasikan reserved fields pada desain format pesan sederhana. Katakanlah Anda sedang mendesain protokol pertukaran pesan antara IoT Device dan Server.

Definisi Struktur Data

// DevicePacket mencerminkan struct C: device_packet_t
type DevicePacket struct {
	MessageType uint16    // 2 byte
	DeviceID    uint32    // 4 byte
	Status      uint8     // 1 byte
	Reserved    [5]byte   // 5 byte
	Timestamp   uint32    // 4 byte
}

// Encode mengubah DevicePacket ke []byte (big-endian)
func (p *DevicePacket) Encode() ([]byte, error) {
	buf := new(bytes.Buffer)
	err := binary.Write(buf, binary.BigEndian, p)
	return buf.Bytes(), err
}

// Decode mengubah []byte ke DevicePacket
func Decode(data []byte) (*DevicePacket, error) {
	var p DevicePacket
	buf := bytes.NewReader(data)
	err := binary.Read(buf, binary.BigEndian, &p)
	return &p, err
}

Catatan: reserved[5] mungkin hanya akan diisi nilai 0x00 oleh pengirim, tapi penerima tetap harus membaca dan mengabaikan field ini.

Alur Pengiriman dan Penerimaan

flowchart LR
    Start -->|Isi struct| Sender[Device]
    Sender -->|Isi reserved = 0| Packet
    Packet -->|Serialisasi| Network
    Network -->|Deserialisasi| Receiver[Server]
    Receiver -->|abaikan reserved| ProsesData

Simulasi kode (Python mock):

package main

import (
	"bytes"
	"encoding/binary"
	"fmt"
	"log"
)

func encodePacket(messageType uint16, deviceID uint32, status uint8, timestamp uint32) []byte {
	buf := new(bytes.Buffer)

	// Tulis sesuai urutan dan endianness
	binary.Write(buf, binary.BigEndian, messageType)
	binary.Write(buf, binary.BigEndian, deviceID)
	binary.Write(buf, binary.BigEndian, status)
	buf.Write(make([]byte, 5)) // reserved 5 byte zero
	binary.Write(buf, binary.BigEndian, timestamp)

	return buf.Bytes()
}

func decodePacket(data []byte) (messageType uint16, deviceID uint32, status uint8, timestamp uint32, err error) {
	buf := bytes.NewReader(data)

	if err = binary.Read(buf, binary.BigEndian, &messageType); err != nil {
		return
	}
	if err = binary.Read(buf, binary.BigEndian, &deviceID); err != nil {
		return
	}
	if err = binary.Read(buf, binary.BigEndian, &status); err != nil {
		return
	}
	reserved := make([]byte, 5)
	if _, err = buf.Read(reserved); err != nil {
		return
	}
	if err = binary.Read(buf, binary.BigEndian, &timestamp); err != nil {
		return
	}
	return
}

func main() {
	// Simulasi
	packet := encodePacket(1, 12345, 2, 1721548800)

	mt, did, st, ts, err := decodePacket(packet)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("type=%d, device=%d, status=%d, ts=%d\n", mt, did, st, ts)
}

4. Reserved Numbers: Studi Kasus Enum & Protobuf

Pada protobuf, sering ditemukan keyword reserved, baik untuk field number ataupun nama. Ini krusial agar pada revisi di masa mendatang tidak terjadi penimpaan yang tidak diinginkan (breaking change).

Contoh Enum dengan Reserved Numbers

enum UpdateStatus {
    UNKNOWN = 0;
    PENDING = 1;
    COMPLETED = 2;

    // Reserved untuk future use
    reserved 100 to 199;
}

Jika nanti di-protobuf definition ada status baru, tinggal tambahkan pada angka di blok reserved. Selain itu, reserved numbers mencegah external developer mengisi enum tersebut dengan nilai 100 - 199 (di plugin atau distribusi custom), sehingga integritas protokol tetap terjaga.

Simulasi Error Ketika Melanggar Reserved

// Ini akan error!
enum UpdateStatus {
    UNKNOWN   = 0;
    RESERVED2 = 120; // <--- Error, masuk di blok reserved
    reserved 100 to 199;
}

Protobuf compiler akan mengeluarkan error, menjaga implementasi tetap disiplin.


5. Reserved Fields di API & JSON

Tak hanya di protokol atau binary, reserved fields sering diadopsi pada REST API berbasis JSON.

Format respons:

{
  "result": "ok",
  "device_id": 12345,
  "reserved": null
}

Di dokumennya dicatat: “Field ‘reserved’ boleh diabaikan, namun wajib disertakan untuk kompatibilitas ke depan.”

Manfaatnya? Ketika v2 rilis, field itu bisa mulai diisi makna baru, tanpa perubahan besar di sisi klien maupun server lama.


6. Reserved Fields/Numbers di Dunia Nyata

TCP/IP Options:
Di header paket TCP, terdapat field ‘Reserved’ 6 bit. RFC menginstruksikan agar nilainya 0, serta diabaikan oleh penerima—siap dipakai untuk future options (sampai kini sebagian memang belum pernah dipakai).

HTTP Header:
Banyak header custom didahului dengan ‘X-’, yang kemudian menjadi konvensi reserved area untuk vendor header, sebelum terstandarisasi.


7. Best Practices Reserved Fields & Numbers

  1. Selalu isi reserved fields dengan nilai default (zero/NULL).
    Pengisi field harus tetap disiplin bahkan jika field tidak digunakan.

  2. Jangan assign makna pada reserved di versi saat ini.
    Penjelasan di dokumentasi dan comment harus explisit:

    // reserved, do not use - for future compatibility

  3. Gunakan reserved numbers untuk “menghalangi” external/plug-in abuse.
    Misal: enum 0-100 untuk protokol inti, 200-250 reserved untuk experimental/extension internal.

  4. Dokumentasi adalah wajib.
    Without documentation, reserved field/number malah membingungkan developer berikutnya.


Kesimpulan

Reserved fields dan reserved numbers adalah strategi matang untuk menjaga agar protokol, API, dan sistem data tetap scalable dan compatible di masa depan. Seperti menyiapkan lahan kosong di sebelah rumah, reserved fields memungkinkan ekspansi tanpa mengusik struktur lama.

Sebagai engineer, disiplin dan transparansi dalam memelihara reserved spot adalah bagian dari engineering culture yang baik. Baik untuk versi berikutnya, maupun untuk generasi developer yang akan datang.


Referensi


Semoga artikel ini membantumu dalam mendesain protokol atau API yang tahan masa depan.

comments powered by Disqus