-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove specialization-related conditional logic from PojoCodecImpl
by introducing LazyPropertyModelCodec.NeedsSpecializationCodec
#1136
Conversation
…by introducing `LazyPropertyModelCodec.NeedsSpecializationCodec` This commit moves some of the conditional logic from `PojoCodecImpl` under the rug, thus allegedly simplifying `PojoCodecImpl`, but not the POJO codec implementation overall. I still have no idea about the following: - What "specialization" means and why it exists? - Why there is two "unusable" types codecs; previously it was `LazyPropertyModelCodec` and some instances of `PojoCodecImpl`, now its `LazyPropertyModelCodec` and all instances of `NeedsSpecializationCodec`? - Why is it so happens that `NeedsSpecializationCodec` is always (I judge based on the existing tests) replaced by `LazyPropertyModelCodec` with a usable codec instance? JAVA-4954
@jyemin I think that this change makes the code a bit simpler. Unfortunately, it does not result in having any new step towards drastically simplifying the POJO codec implementation. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great questions - I had to dive through the code to understand it more.
- What "specialization" means and why it exists?
Originally, the CodecRegistry
could only handle classes eg: registry.get(MyPojo.class)
. "specialization" just means setting the concrete types parameters for a POJO's property.
public final class NestedSelfReferentialGenericHolderModel {
private NestedSelfReferentialGenericModel<Boolean, Long, Double> nested;
}
public final class NestedSelfReferentialGenericModel<T, V, Z> {
private SelfReferentialGenericModel<T, V> selfRef1;
private SelfReferentialGenericModel<T, Z> selfRef2;
}
public final class SelfReferentialGenericModel<T, V> {
private T t;
private V v;
private SelfReferentialGenericModel<V, T> child;
}
With the above POJOs, we have enough data to model all the POJOs for the properties. However, we have some cyclical considerations as SelfReferentialGenericModel
is self referential.
Specialization is also used to handle the SelfReferentialGenericModel
codec and its appropriate types when set per property.
- Why there is two "unusable" types codecs; previously it was LazyPropertyModelCodec and some instances of PojoCodecImpl, now its LazyPropertyModelCodec and all instances of NeedsSpecializationCodec?
LazyPropertyModelCodec
just defers the handling of a property's generic types until its actually used to decode/encode data. Hence breaking any cycles.NeedsSpecializationCodec
means we have no type data at that point in time. This happens when a POJO containing type parameters is used withcodecRegistry.get(clazz)
.
- Why is it so happens that NeedsSpecializationCodec is always (I judge based on the existing tests) replaced by LazyPropertyModelCodec with a usable codec instance?
Nearly always ;) There are two causes; direct use like in testCannotEncodeUnspecializedClasses
Or via the FallbackPropertyCodecProvider
.
(This would be the place to actually call the registry with the TypeArguments as they are effectively lost after this point - we should open a ticket for that).
As NeedsSpecializationCodec
is a PojoCodec
the LazyPropertyModelCodec
both creates and replaces it when calling createCodec
- which has a code smell.
I like the PR - just a couple of comments
@@ -50,36 +50,28 @@ | |||
private final CodecRegistry registry; | |||
private final PropertyCodecRegistry propertyCodecRegistry; | |||
private final DiscriminatorLookup discriminatorLookup; | |||
private final boolean specialized; | |||
|
|||
PojoCodecImpl(final ClassModel<T> classModel, final CodecRegistry codecRegistry, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the constructors can now be chained - ie. this one calls the below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wish ... : one of them (PojoCodecImpl(final ClassModel<T> classModel, final CodecRegistry codecRegistry, final List<PropertyCodecProvider> propertyCodecProviders, final DiscriminatorLookup discriminatorLookup)
) has to give this
to a new PropertyCodecRegistry
, which means that this constructor can neither be called from the other one, nor the other one can call this one.
As far as I can see, only refactoring of the code around PojoCodecImpl
may open up opportunities to either calling one of the constructors from the other, or getting rid of one of them. But I don't even know if such refactoring is possible, and if yes, what it will look like.
this.classModel = classModel; | ||
this.registry = codecRegistry; | ||
this.discriminatorLookup = discriminatorLookup; | ||
this.propertyCodecRegistry = propertyCodecRegistry; | ||
this.specialized = specialized; | ||
specialize(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this specialize()
logic now be moved into the constructor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless we want to duplicate a bunch of code, this can only be done if one of the constructors reuses the other one, which does not seem possible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This PR moves some of the conditional logic from
PojoCodecImpl
under the rug, thus allegedly simplifyingPojoCodecImpl
, but not the POJO codec implementation overall.I still have no idea about the following:
LazyPropertyModelCodec
and some instances ofPojoCodecImpl
, now itsLazyPropertyModelCodec
and all instances ofNeedsSpecializationCodec
?NeedsSpecializationCodec
is always (I judge based on the existing tests) replaced byLazyPropertyModelCodec
with a usable codec instance?JAVA-4954