Target Entity

Lately I’ve been fighting with some teory vs practice which refused to cooperate and that’s become a bit frustrating. My problem was an API which looked OK but when time came to persist it with JPA entities it needed so much tweaking, pushing and pulling generics to get that covariant return to work that really felt something was terribly wrong. The point was to write an API which would allow the persistence layer implement it and still be manageable and targeted by the entity manager, but something wasn’t fitting.

First approach was to define types together with class declaration.

public class Application <T extends Applicant> {}

This led to a very complex to design API because it kept extending the generic types as relationships appeared, which in time caused the API to be hard to understand because the attention on what it was trying to solve was caught by the types definition and declarations growing larger and larger as a second and a third type needed to be defined. Clear bad smell, so first refactoring took place. This first approach is depicted in package ec.pazmino.sandbox.generics.api.interfaces and its JPA entities implementation in ec.pazmino.sandbox.generics.api.jpa

To solve this I decided to declare generic types inline so interfaces would look cleaner.

public class Application {
(<T extends Applicant>) T applicant;

They did look cleaner. But the API got even harder to use and made me realize how much left I had to learn on generics. It’s a lot. These are packages ec.pazmino.sandbox.generics.api.interfaces.inline and ec.pazmino.sandbox.generics.api.interfaces.jpa.inline. So I started reading some more on generics and was about to start a new approach, which should lay an easier way to sub-classing by declaring types as self-referenced >.

But then I re-read the problem: a “covariant return which would allow the persistence layer implement the API and still be manageable and targeted by the entity manager.” All the magic remained calm in one word: “targeted”. This truth was revealed to me at 3:30 am. All I needed was telling the entity’s relationship what the specific target was implementing the defined contract. That’s it. The covariant return is given by the definition of the interface itself; anyway typing is going to be deleted after compilation. These are packages ec.pazmino.sandbox.generics.api.interfaces.clean and ec.pazmino.sandbox.generics.api.interfaces.jpa.clean

Such an easy thing became a mess because I was trying to solve it with the wrong tool. Covariant return is not necessarily solved with generics because a

covariant return type, means that the return type is allowed to vary in the same direction as the subclass.

Code repo


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s