Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoid duplicate code with numerous Java classes sharing fields

I'm working on an application which writes on a NoSQL database (Elasticsearch to be precise) and I have to manage more than a dozen (the number grows with time) different document classes, that is classes with numerous fields, their getters and setters and methods to convert the class to a JSONObject (each field is annotated with @JsonProperty(PROPERTY_NAME) and we use a JSON parser ).

All these classes have some fields and methods in common, which are all contained in a superclass (let us call it DocZero) but they all have their own custom fields, which brings me to the point.
It is true that these fields are custom, but some are shared between different classes in a non-linear way, that is I have my document classes Doc1, ... DocN and I have some sets of fields (around 10 as of right now) shared by them in a very wild way.

Some examples to best convey the situation:
Doc1 contains Set1 to Set5;
Doc2 contains Set1, Set2 and Set5 to Set8;
Doc3 contains Set6 and Set7;
Doc4 contains Set5 and Set7;
Doc5 contains Set1, Set2, Set5 and Set7 to Set10.

Given that I need to get and set these fields and, from time to time, manipulate a document with them, I made interfaces out of the Set#, each containing (abstract) setters and getters.
As such, when I declare a class

public class DocX implements SetA, SetB, SetC

I get reminded to implement the methods and hence add the required fields, but this means that all the classes implementing the same set will need to have the same parameters and the same methods which means that I need to write the same code many times (sometimes more than getter and setter methods).

Adding all the fields to DocZero foregoing the different Doc# classes is a solution which I am not keen on using, since I prefer to distinguish different document types and since this situation is present, in lower magnitude, in another section of the code, with AnotherDocZero, AnotherDoc# and AnotherSet# for which merging cannot be done due to other constraints and for which I would like a potential solution to work too.
I feel like this is one of those situation where multiple inheritance would solve the issue, but unfortunately Java doesn't allow it.

How could I avoid duplication in a situation like this? Have you got any advice to improve my handling of this issue?

like image 368
Ukitinu Avatar asked Jan 25 '23 21:01

Ukitinu


2 Answers

I strongly suggest to keep your data classes simple even if it does mean that you will need to repeat many fields definitions - POJOs are definitely easier to maintain and understand how the "result" data object looks like if you have all fields in one place - multilevel inheritance will quickly create a mess

For constraints of having proper getters you should use interfaces as you do. You can even create single interface for every getter and group them in another one like

public interface Set1To5 extends Set1, Set2, Set3, Set4, Set5 {}

For avoid duplication of getters/setters you can use some additional lib like lombok or consider not using getters/setters at all (just make all the fields in your data document classes public - but this one of course is not the option if you need to constraint classes with interfaces)

like image 36
m.antkowicz Avatar answered Jan 30 '23 05:01

m.antkowicz


If several kinds of fields are often grouped together, that suggests that grouping is a natural part of the domain of your program, and should be represented as such.

So, if you often find this in your classes

   int xCoordinate;
   int yCoordinate;

You should instead introduce

public final class Point ... {
   private final int x;
   private final int y;

   Point(int x, int y) {
      ...
   }

   ...
}

then instead of repeating x and y, write

   Point position;
like image 153
Raedwald Avatar answered Jan 30 '23 03:01

Raedwald