matsim: immutable types?

Description

Dear Marcel, Thibaut,

I am once more fighting with immutability. "Effective Java" recommends to favour immutability. I think that the potential advantages for parallel computing are evident.

However, in matsim we have always been fighting with this. The "population" was deliberately designed as an object-oriented database in memory, and as such was in fact designed around explicity mutability, and all efforts to make, say, routes immutable lead to awkward code.

I am now fighting with a similar situation within the Vehicles data hierarchy. The item of contention is vehicle.getType(), and if the returned VehicleType should be immutable. It was designed as such in the "freight" contrib. But not in the matsim core. I would like to have it consistent.

Consider the use case that, at some point, we want a 10% fuel efficiency improvements for some of our engine types . If vehicle types are immutable, we would need to replace the vehicle type for the affected vehicles:

for ( vehicle : vehicles ) {
if ( affectedType.equals( vehicle.getType() ) ) {
vehicle.setType( improvedType ) ; // (#)
}
}

The problem now comes if some code has kept a separate reference to the vehicleType. (Don't say that this does not happen; look at CarrierVehicleTypes.)

One thing that we could do would be to agree that "types" in the matsim scenario are immutable. This would imply that one should never keep references to such types, always go back to vehicle.getType() etc. when needed. But we would need that as agreement, otherwise it gets confusing to teach.

"Types" would be items of which we have a small number (such as vehicle types, activity types, road types, etc.), and which are referenced by our "physical" elements (persons, vehicles, signals, links, ...).

Do you have any thoughts on this?

Thanks and best wishes

Kai

PS: Some more material, maybe TL;DR

Evidently, one could say that vehicle itself should be immutable, i.e. line (#) should also not be possible, but then in use case we would need to replace the vehicle, and we have the same problem if someone keeps a reference to the vehicle. Overall, the problem will always be there, only pushed up or down. Still, I can imagine that someone caches the result of

vehicle.getType() ;

I cannot imagine that someone caches the result of

vehicle.getCapacity().getSeats() ;

MZ at some point said that this is just the way it is in Java: If you do

Person person = createPerson() ;
population.addPerson( person ) ;
person.addPlan(...) ;

we expect that we can keep the reference to person and can still work on it later.

Note that for "computation" (e.g. routing, mobsim), we already copy data from scenario to somewhere else, so those modules can construct their own data structures.

======================================================

Clone github.com/matsim-org/matsim-example-project<http://github.com/matsim-org/matsim-example-project> to get started.
Look at github.com/matsim-org/matsim-code-examples<http://github.com/matsim-org/matsim-code-examples> for code examples.
Also see matsim.org/downloads<http://matsim.org/downloads> | matsim.org/docs/tutorials<http://matsim.org/docs/tutorials> | matsim.org/open-scenario-data<http://matsim.org/open-scenario-data> | matsim.org/faq<http://matsim.org/faq> .


www.vsp.tu-berlin.de<http://www.vsp.tu-berlin.de>
+49 30 314 23308 (phone) +49 30 314 26269 (fax)
postal: TU Berlin Sekr. SG 12, Salzufer 17-19, 10587 Berlin
physical: building SG 4.1, room 305
[Created via e-mail received from: "Nagel, Kai, Prof. Dr." <nagel@vsp.tu-berlin.de>]

Environment

None

Activity

Show:
Marcel Rieser
September 11, 2019, 6:58 PM

For immutable types to expand their full power requires a special API design, I think. Otherwise they might indeed rather be limiting. As MATSim is generally designed for mutable data types, it would be okay to have vehicle types also mutable.

There is the problem that somebody might be doing something like vehicle.getType().setSomething() and thus accidentally changing the type of hundreds of vehicles instead of only of this one vehicle. On the other hand, we already have similar situations with mutable Coord}}s that could be re-used in several places, but we never had a problem with it (to my knowledge). It could also be argued that if you do something like {{vehicle.getType().setSomething() and expect to only modify this specific vehicle, that you did not understand the API.

Thibaut Dubernet
September 12, 2019, 7:38 AM
Edited

Is there any guarantee that vehicle.getType().setFoo(42) indeed sets the foo property for all vehicles of that type? That is, are types guaranteed to be a singleton for instance by forcing creation using a factory that caches one instance per type name (the same way e.g. Ids are)?

If so, I would not have a problem with it, as we indeed mostly use mutable objects, and mutable objects make scenario creation much easier (which is, I think, the main use case for java for a lot of users).

If not, I find this dangerous, and would strongly favor immutable objects.

Kai Nagel
September 13, 2019, 1:19 PM

There is no guarantee. It is not the same as with Id. It is the same as with the Node references in Link: If someone really tries to abuse it, he/she can do it. That is:

  • First the vehicle types are read in and build. Two types cannot be registered behind the same type id.

  • When the vehicles are build, each vehicle gets a Java reference to a type.

  • If someone changes the type, this is changed for all vehicles that reference to that type.

If, however, someone insists of building a new type with an already existing typeId, not register it centrally, and then give it to a vehicle, then she can do that.

Note that vehicleTypes and vehicles are typically in the same file, so we are not referencing across files. (Unfortunately, this is not the case in the freight contrib, and it actually causes problems there. But I think that has to solved in the freight contrib, not in the matsim core.)


I am not against implementing something as with Id. Myself I don’t know how to do it, and won’t have the time to learn it in the foreseeable future.


I tried immutable. I think that the way to go would be to have builders for everything, and once the objects are built they only have getters. It really becomes quite awkward … see separate discussion elsewhere. If we want immutable in parts of matsim, I think that we should all try to implement it for some use case, and then discuss it.

Assignee

Thibaut Dubernet

Reporter

Kai Nagel

Labels

None

Priority

Major
Configure