オブジェクトをイミュータブルにすることに対する肯定的な意見はネット上に溢れているし、それには僕自身も納得しているのですが、次の例のようにオブジェクト同士が相互参照している場合はどのように対処すればよいのでしょうか?
例えば、次のようにイミュータブルなPerson
とPet
クラスがあったとします(擬似コードです)。
class Person { final String name; final int age; final ImmutableList<Pet> pets; } class Pet { final String name; final Person owner; }
これを使って次のような処理をします。
me = Person(name:'yamada', age:30, pets:[]); cat = Pet(name:'dora', owner:me); // me.petsにcatを追加 // immutableなので me!=me_1 me_1 = me.copyWith(pets: me.pets + cat);
すると、me_1
とcat
は相互参照している状態になります。このあとme_1.age
を30から40に変更しようと思ったら
me_2 = me_1.copyWith(age: 40);
とすれば良いわけですが、これだけだとcat.owner
が古い方(me_1
)を参照したままになってしまうので、そちらの方も書き換える必要があります。
cat_1 = cat.copyWith(owner: me_2);
このようにイミュータブルなオブジェクトが相互参照していると、片方が変化するたびに(参照の整合性を保つために)もう片方も修正する必要があります。今回の例はシンプルな相互参照でしたが、この参照の関係がもっと複雑になればなるほど整合性を保つのが大変になってしまうはずです。このような場合、どのようにして対処すればよいのでしょうか?それとも、イミュータブルなオブジェクト同士が相互参照するような設計は避けるべきでしょうか?