ValueObjectっぽいものを導入したらいい感じになってきた

今までAPIで取得した値を加工・計算したい場合とりあえず連想配列に入れてゴニョゴニョしていた。
連想配列にいろいろなデータ詰め込みすぎると何入ってるのかわかんなくなるし、面倒なのがある条件のときだけ存在しないキーがあったりしたら、isset()とかempty()で確認するif文が増えてわけわかんなくなる。

<?php
// こういうの。nullだったり、キーがなかったりする。
Array
(
    [0] => Array
        (
            [key] => Array
                (
                    [key] => value
                    [key2] => value
                )

        )
    [1] => Array
        (
            [key] => Array
                (
                    [key] => null
                )

        )

)

さらにforeachで回してデータを取り出して保存するみたいな処理の場合、ロジックがあちこちに重複してしまっていたりする。
例えば、ある値は0~100までの値しか入っていないことを期待しているのだけど、本当に0~100までの値しか来ないのか、間違って変な値が入っていたら困るのでこういうif文を書くことになる。

<?php
        if (0 <= $value && $value <= 100) {
           $this->foo();
        }

それで今日も今まで通り連想配列に入れてテスト書いたり、ソートして最小値取り出すみたいなことしてたんですが、やっぱダメだなこれみたいに思って、ValueObjectみたいな入れ物クラスを作ってみたら、これが良かった。
まずPHPDocを書いたら補完が効くからキー名を間違える心配がない。オブジェクトが入った配列をforeachで回してデータを取り出すときに楽。配列に何が入っているのかを考えてキー名を自分で書く必要がない。

<?php
    /**
     * @param Value[] $data
     * @return array
     */
    public function getData(array $arr): array
    {
        $data = [];
        foreach ($arr as $row) {
   // ここで補完が効く
            $data[] = $row->getMin();
        }
        return $data;
    }

あとは上記のちょっとしたif文をどこに書くべきか迷わなくて済む。
こういうちょっとしたif文のために新しいクラスを作るのはおかしい気がするし、ヘルパー関数とかに書くのも釈然としない。
でもValueObjectのコンストラクタに書けば、テストも書きやすいし、入っていい値のルールみたいなロジックがあちこちに重複することもない。

<?php
public function construct(int $value)
{
        if (0 > $value || 100 < $value) {
           throw new InvalidValueException("value:{$value} 不正な値です");
        }
}

これをValueObjectと呼ぶべきなのかはわからないけど、なんかちょっとしたブレークスルーになった気がした。