不変オブジェクトを使用すると、参照を共有することでオブジェクトの値を共有するコードが可能になります。ただし、可変オブジェクトには、参照を共有することによってオブジェクトのIDを共有したいコードのIDがあります。ほとんどのアプリケーションでは、両方の種類の共有が不可欠です。使用可能な不変オブジェクトがない場合は、新しいオブジェクトまたはそれらの値の目的の受信者によって提供されたオブジェクトに値をコピーすることで、値を共有できます。可変オブジェクトなしで取得するのははるかに困難です。stateOfUniverse = stateOfUniverse.withSomeChange(...)
と言うことで、可変オブジェクトをいくらか「偽造」することができますがstateOfUniverse
、withSomeChange
メソッドが実行されています[あらゆる種類のマルチスレッドを排除します]。さらに、たとえばトラックのフリートを追跡しようとしていて、コードの一部が特定のトラックに関心がある場合、そのコードは、変更された可能性があるときはいつでも、トラックのテーブルでそのトラックを常に検索する必要があります。 。
より良いアプローチは、宇宙をエンティティと値に細分化することです。エンティティは変更可能な特性を持ちますが、アイデンティティは不変であるため、たとえばタイプの保管場所はTruck
、トラック自体が位置を変更したり、貨物を積み降ろししたりする場合でも、同じトラックを識別し続けることができます。しかし、不変の特性を持っているでしょう。ATruck
は、その場所をタイプとして保存する場合がありますWorldCoordinate
。45.6789012N 98.7654321Wを表すAWorldCoordinate
は、それへの参照が存在する限り継続します。その場所にあったトラックがわずかに北に移動した場合、WorldCoordinate
45.6789013N 98.7654321Wを表す新しいトラックが作成され、古いトラックは破棄され、その新しいトラックへの参照が保存されます。
すべてが不変の値または不変のIDのいずれかをカプセル化し、不変のIDを持つはずのものが変更可能である場合、コードについて推論するのが一般的に最も簡単です。変数の外部で可変オブジェクトを使用したくない場合stateOfUniverse
、トラックの位置を更新するには、次のようなものが必要になります。
ImmutableMapping<int,Truck> trucks = stateOfUniverse.getTrucks();
Truck myTruck = trucks.get(myTruckId);
myTruck = myTruck.withLocation(newLocation);
trucks = trucks.withItem(myTruckId,myTruck);
stateOfUniverse = stateOfUniverse.withTrucks(trucks);
しかし、そのコードについて推論することは、次の場合よりも難しいでしょう。
myTruck.setLocation(newLocation);