Context :
We have a service that accepts a POST submission for an entity. Let us call that entity E. The entity can have various attributes - A,B,C,D. Let us say attribute A is the primary key for entity E.
When the service receives a submission, the submission does not need to be complete i.e. it need not have all attributes present apart from the primary key A. If we already have an object in our datastore corresponding to A, we fetch that object, override the stored attribute values with submission attribute values and persist that again. If we have no object stored corresponding to A, we apply some defaulting logic and apply default values to missing attributes before persisting that object to our data store.
So the difference in behavior is that submission may or may not have some attributes present but once that object is stored, all attributes will always be present.
Question : In terms of data modeling, I have two options described below. I want to understand which is the recommended way of modeling such behavior and why. :
OPTION 1: Two interfaces treating Optional as contract :
interface EntitySubmission {
A getA(); // Since this is a primary key it will always be present
Optional<B> getB();
Optional<C> getC();
Optional<D> getD();
}
AND
interface EntityPersisted {
// No attribute will ever be missing or null
A getA();
B getB();
C getC();
D getD();
}
OPTION 2 : Single unified interface treating Optional as convenience :
interface Entity {
A getA();
Optional<B> getB();
Optional<C> getC();
Optional<D> getD();
}
NOTE : Please note that the intent of OPTION 1 is to clarify the expectation that no attribute will ever be missing or null for objects of type EntityPersisted.
EDIT : I think the core of this question got lost in the Optional debate. The core of my question is whether I should declare separate interfaces to convey separate expectations(Nullable vs NonNull) or have a single unified interface allowing nullable non-key attributes?