-
Notifications
You must be signed in to change notification settings - Fork 4
schema overview
Almost every system design starts with defining domain models, what do they consist of and how they relate to each other. This is the language PMs and customers understand and it allows to set up universal dictionary for interfaces and implementations. So lets start with a few abstract entities:
Every entity can be described by multiple representations: ID, URI, record or even binary data like images. We can capture this concept by introducing multi-types, collections of types that can act as different representations of the same entity.
User
is a multi-type that can be either UserId
or UserRecord
, File
can
be either FileId
or FileRecord
and so on.
Now we have records, fields and field types. FileRecord.name
is probably
a string, but what’s the type of FileRecord.owner
? Before deciding on it lets
step back and think about the nature of a field. Fields define relationships
between entities and field names hint at their semantics. We don’t care about
implementation details at this point, all we want to say is that a File
has an
owner which is a User
owner
field can hold any representation of a User
, and so it's type should
naturally be User
. But what happens when a client asks to fetch a file record
with name and owner fields without specifying which representation of the owner
to build? Should we fail or build a random one? This uncertainty can be solved
by adding one more property to the multi-type, a default type.
todo: default type should also be overridable on a per-field basis, either on the schema or IDL level. Update this doc when refined
So now we can say that User
is a multi-type which can be either a UserId
or
a UserRecord
, and by default it is going to be a UserId
Multi-type is a collection of types that can act as different representations of the same entity type. This is not always an "is-a" relationship, so we can't model it as inheritance, this is more of "can-be".
Instances of multi-types are called multi-values and are modelled as records,
with field names being type aliases. For example FileRecord.owner
of type
User
can contain
{
'userId' : data
}
or
{
'userRecord' : data
}
or even both at the same time:
{
'userId' : data,
'userRecord' : data
}