I am really reconsidering my current class hierarchy for timeslots (in a schedule). I wanted to make them as flexible as possible so it would cover many possibilities of what we could understand as a timeslot, so I ended up with this design:
All timeslots share a chronological/hierarchical order so we're able to define comparing functions. It provides the most basic means of determining if a timeslot comes before or after another.
public interface Timeslot extends Comparable<Timeslot> {
int getChronologicalOrder();
}
This is the "base" timeslot, it just has a chronological order integer.
public class AbstractTimeslot extends Entity implements Timeslot {
protected final int chronologicalOrder;
}
This is for timeslots that define a range, that is, the span of the timeslot in the schedule, for example 10 minutes, 1 hours, 3 days, etc... To represent this we use a TemporalAmount
member. However, the starting point of the timeslot is unknown or irrelevant.
public abstract class RangedTimeslot extends AbstractTimeslot {
protected final TemporalAmount duration;
}
Then we have this timeslot which is like the previous one but it does define a definite starting point using the Java 8 interface TemporalAccessor
. This way we can say when a timeslot starts, like a particular day or hour with LocalDate
, LocalTime
, DayOfWeek
, etc.
public class DefiniteTimeslot extends RangedTimeslot {
protected final TemporalAccessor start;
}
Finally there's this timeslot that doesn't define a duration because it is unknown or irrelevant, but we know the starting time. It is exactly like a RangedTimeslot
but I wanted to keep this last one as an abstract
class in case we needed further hierarchy expansion.
public class UndefiniteTimeslot extends RangedTimeslot {}
Visually, this is how the hierarchy looks like:
Now I am wondering if this is making things harder than they actually are. The first big wall I am facing with this design is that now I need to serialize and deserialize as JSON many of my classes, like Tournament
and Schedule
, and they include these timeslot classes. This kind of polymorphism makes it kind of a hell to deal with serialization and deserialization (I am using Jackson), so I just started wondering if this is a good design and if it'd be a good idea to "simplify" it. I'd still have to face the polymorphism problem of TemporalAmount
and TemporalAccessor
but that's kind of inevitable.
I think the other way of thinking this scenario is cutting the whole tree and be left with just a Timeslot
class with Optional
members so every situation where we want undefined starting times and/or undefined timeslot span are covered. We would end up with a class more or like the one that follows:
public class Timeslot extends Comparable<Timeslot> {
private int chronologicalOrder;
private final Optional<TemporalAccessor> start;
private final Optional<TemporalAmount> duration;
public Timeslot(int c) {
chronologicalOrder = c;
start = Optional.empty();
duration = Optional.empty();
}
public Timeslot(int c, TemporalAccessor s) {
chronologicalOrder = c;
start = s;
duration = Optional.empty();
}
public Timeslot(int c, TemporalAmount d) {
chronologicalOrder = c;
start = Optional.empty();
duration = d;
}
public Timeslot(int c, TemporalAccessor s, TemporalAmount d) {
chronologicalOrder = c;
start = s;
duration = d;
}
}
What do you think is the best design? Should I dump my current hierarchy and take the last solution? Would it make testing the class easier? (I already have tests for the current design)
TemporalAccessor
andTemporalAmount
serialization/deserialization is a bigger issue that the hierarchy itself, tbh.TemporalAccessor s, TemporalAmount d
", how do you expect people using this type to internalise the rules of that function?