> Indeed, the current implementation appears to have several problems. So,
> how about the following implementation?
>
> ```php
> interface RandomNumberGenerator
> {
>     public function generate(): int;
> }
>
> final class Random
> {
>     private RandomNumberGenerator $rng;
>     public function __construct(?RandomNumberGenerator $rng = null)
>     {
>         $this->rng = $rng ?? new XorShift128Plus(random_int(PHP_INT_MIN,
> PHP_INT_MAX));
>     }
>     public function nextInt(): int {}
>     public function getInt(int $min, int $max): int {}
>     public function getBytes(int $length): string {}
>     public function shuffleArray(array $array): array {}
>     public function shuffleString(string $string): string {}
>     public function __serialize(): array {}
>     public function __unserialize(array $data): void {}
> }
>
> class XorShift128PlusNumberGenerator implements RandomNumberGenerator
> {
>     public function generate(): int {}
>     public function __serialize(): array {}
>     public function __unserialize(array $data): void {}
> }
>
> class MT19937NumberGenerator implements RandomNumberGenerator
> {
>     public function generate(): int {}
>     public function __serialize(): array {}
>     public function __unserialize(array $data): void {}
> }
>
> class SecureNumberGenerator implements RandomNumberGenerator
> {
>     public function generate(): int {}
> }
> ```
>
> This is an approach similar to Nikita's `createDefault`. If the
> constructor has a null argument, it uses the default, XorShift128+,
> internally.
>
> Also, whether the Random class is serializable or clonable depends on the
> instance of RandomNumberGenerator being used. This means that when the
> Random class clone is called, the `$rng` member will be implicitly cloned.
>
> How about this?
>

Hello, thanks for thinking again.

A few editorial notes:
- I guess that would be "new XorShift128PlusNumberGenerator" (like the
class name)?
- The non-Secure implementations' stubs are probably missing `public
function __construct(?int $seed = null) {}`?
- The Random class' and non-Secure implementations' stubs are probably
missing `public function __clone(): void {}` (like `__serialize()`)?

That would let us use the API like this:

1. Construction: one of:
    - default RNG and seed: `$random = new Random();`
    - chosen RNG, default seed: e.g. `$random = new Random(new
MT19937NumberGenerator());`
    - chosen RNG and seed: e.g. `$random = new Random(new
MT19937NumberGenerator(1234));`
    (no "default RNG, chosen seed", but the default RNG can be documented,
and one could argue that a chosen seed only makes sense with a chosen RNG
anyway)

2. Usage: `$int = $random->nextInt();`, `$percent = $random->getInt(0,
100);`, `$dword = $random->getBytes(4);`, `$shuffledList =
$random->shuffleArray($list);` etc.

I think this is well-consistent with the "pure design" described by Nikita,
and I personally find it both flexible/extensible and easy-to-use =)
(Just beware that the namespace question will probably pop up again.)

PS: I feel like my numerous questions/suggestions (in this thread and the
previous ones) may also have caused some deviations, so I hope that I won't
need more and that other participants will reach a consensus...

Best regards,

-- 
Guilliam Xavier

Reply via email to