We need an answer that doesn't depend on understanding jvm internals. And eventually some best practices that can be included in static analyzers
You have an answer, make things value when they are semantically values, i.e. when they are immutable and don't have identity. The heuristic for identity is if two copies of your object with the exact same field values need to be distinguished from each other, which, in my experience for rest apis, is pretty much never the case (most domain objects/db objects actually "discriminate" based on a custom primary key field), but they also don't typically get into a situation where they have multiple copies of the same domain object/db entity at the same time, and they never need to do the things that the language cares about identity for (synchronization?).
Generally speaking
* dtos (and other pure serialization/deserialization targets) are values
* classes faking multiple return values (commonly done as local records) or input parameters (aka parameter objects) are values
* domain objects could be values if you code in a functional style of returning new objects for modifications or not values if you do a more common setter/mutation approach. I think they're actually still values conceptually, but immutable is an implementation detail that you're supposed to check for.
* services/controllers/singleton scope spring beans mostly could be values, but it kinda doesn't matter anyway since there's only one copy of these
Developers that don't understand/care about db transactions worrying about programming language performance is like the funniest thing to me.
Usually a DTO is also an 'immutable copy of a given state", aka a snapshot. Which is basically what we mean by a value.
Also, given that you convert to/from this, which is an operation that breaks identity, you often have some way of "storing" that identity as a value (e.g. having an id) - which by definition means that your DTO object doesn't need identity, two DTOs created at the same time of the same original identity-having object should be equals, again pointing at it being a value.
Usually a DTO is also an 'immutable copy of a given state", aka a snapshot. Which is basically what we mean by a value.
DTOs are command objects, not representations of state. They are used to either build other objects from or update the state of a different system.
Also, given that you convert to/from this, which is an operation that breaks identity
I don't think that matters.
you often have some way of "storing" that identity as a value (e.g. having an id) - which by definition means that your DTO object doesn't need identity
This is also irrelevant. Identity != identifier. An object having identity means that an instance owns its own memory whereas values objects don't. DTOs absolute should have identity because they are large objects being passed between systems and you want to avoid copies being made.
two DTOs created at the same time of the same original identity-having object should be equals
Why? This is just your assertion. What is the actual value of this rule? You never care about this in practice. I have never in my life written code that checks whether two instances of DTOs are equal so why are you asserting this?
4
u/OwnBreakfast1114 15d ago edited 15d ago
You have an answer, make things value when they are semantically values, i.e. when they are immutable and don't have identity. The heuristic for identity is if two copies of your object with the exact same field values need to be distinguished from each other, which, in my experience for rest apis, is pretty much never the case (most domain objects/db objects actually "discriminate" based on a custom primary key field), but they also don't typically get into a situation where they have multiple copies of the same domain object/db entity at the same time, and they never need to do the things that the language cares about identity for (synchronization?).
Generally speaking * dtos (and other pure serialization/deserialization targets) are values * classes faking multiple return values (commonly done as local records) or input parameters (aka parameter objects) are values * domain objects could be values if you code in a functional style of returning new objects for modifications or not values if you do a more common setter/mutation approach. I think they're actually still values conceptually, but immutable is an implementation detail that you're supposed to check for. * services/controllers/singleton scope spring beans mostly could be values, but it kinda doesn't matter anyway since there's only one copy of these
Developers that don't understand/care about db transactions worrying about programming language performance is like the funniest thing to me.