Java RandomGenerator: เปลี่ยนอัลกอริทึมสุ่มโดยไม่ผูก Business Logic กับ Random
โค้ดที่รับ java.util.Random โดยตรงผูกทั้ง API และอัลกอริทึมไว้ก้อนเดียว Java 17 เพิ่มสัญญากลาง RandomGenerator ให้ business logic ขอเพียง “แหล่งเลขสุ่ม” ส่วนจุดประกอบระบบเลือก implementation ผ่าน factory ได้ คล้ายเครื่องชงที่ใช้หัวต่อมาตรฐานแต่เปลี่ยนกลไกภายในครับ
import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
public class Main {
static int pickIndex(RandomGenerator generator, int size) {
if (size <= 0) throw new IllegalArgumentException("size must be positive");
return generator.nextInt(size);
}
public static void main(String[] args) {
RandomGeneratorFactory<RandomGenerator> factory =
RandomGeneratorFactory.of("L64X128MixRandom");
RandomGenerator first = factory.create(42L);
RandomGenerator second = factory.create(42L);
int a = pickIndex(first, 10);
int b = pickIndex(second, 10);
assert a == b : "same algorithm and seed must reproduce the sequence";
assert a >= 0 && a < 10 : "index must stay inside the bound";
System.out.println("reproducible index: " + a);
}
}
Seed มีไว้ทำซ้ำ ไม่ใช่ทำให้ปลอดภัย
test ควรสร้าง generator ด้วย algorithm และ seed คงที่ ทำให้ failure ทำซ้ำได้ แต่ห้ามยึดตัวเลขผลลัพธ์ชุดหนึ่งข้าม JDK โดยไม่อ่านสัญญาของ implementation—สิ่งที่เราควรทดสอบคือ invariant หรือ pin algorithm ชัดเจนใน test fixture
production simulation อาจต้องการ stream แยกเพื่อรันขนาน ส่วน load balancing อาจสนใจ throughput และ statistical quality ต่างกัน Factory ช่วยค้น algorithm ตาม capability ได้ แต่การเลือกควรวัดกับ workload จริงและบันทึกชื่อใน config ไม่ใช้ “default ที่เร็วที่สุด” แบบเงียบ ๆ
ที่สำคัญ PRNG กลุ่มนี้ไม่ใช่ SecureRandom อย่าใช้สร้าง token, reset link, API key หรือค่าที่ผู้โจมตีเดาแล้วได้ประโยชน์ สำหรับ secret ให้ใช้ API cryptographic ที่ออกแบบมาโดยเฉพาะ การเปลี่ยน interface ช่วยเรื่องสถาปัตยกรรม ไม่ได้เปลี่ยนธรรมชาติทางความปลอดภัยของ algorithm
Recap
- รับ
RandomGeneratorที่ business boundary - เลือก factory/algorithm ใน composition root
- ใช้ seed คงที่เพื่อทำ test ซ้ำได้
- ใช้
SecureRandomแยกสำหรับค่าลับครับ