Skip to content
This repository was archived by the owner on Jul 10, 2022. It is now read-only.

Model Hierarchy

Ian Castaño edited this page Aug 21, 2020 · 5 revisions

The hiearchy for a model called Thing would start with an empty interface called Thing.Partial that extends PartialModel. For every sub-group of Thing fields that are sent/received together, there would be an interface extending Thing.Partial that declares getter methods for those fields only.

At the bottom of the hiearchy would be an interface called Thing.Complete that extends Model and ALL of the Thing parts. Any fields that are not declared in any of the parts should be declared in the complete model.

What is a model?

A model will always preserve the default MongoDB well-known identification system: The ObjectId, so, every Model to be stored at the database will have at least an _id field.

Also the model will be accompanied by two Instant called getCreatedAt() and getUpdatedAt(), automatically generated by the backend.

Defining Model Properties

Every model should have this annotations well defined in order to work correctly with the service system:

  • @ModelProperties.RouteKey: Will be used as prefix to match the backend default route system. (Eg: friends will return BACKEND + /friends/).
  • @ModelProperties.Cache: Every model can be cached to Redis with a certain expiration time. By default it will always be 120 seconds. If you don't want it to be cached you can make it 0.

Creating a Friendship Model

We will create a simple friendship model, where we reference a user who sends the request and one who receives it. A normal example of an abstraction that does this would be the following:

interface Friendship extends Model {
    String getSender();
    String getReceiver();
}

However, there will be times when we want to add an additional part to this model and we will not want to have to pass all the parameters. For example: We want to add the function that an administrator forces the friendship between two people and it depends on him if this action will be silent or will be shown to the players.

In this case we can divide the friendship model into two parts, the first one that is in charge of the Relationship between the two, which is going to be strictly necessary (since we are not going to have a relationship between a single person) and the second one that will be available only in case that an administrator Forced the relationship. Let's take a look:

interface FriendshipDoc {
    
    // In this case we will create an own interface that extends PartialModel functionallity
    interface Partial extends PartialModel {}

    // Remember that any interface extending PartialModel will grant the right to use a Creation Service
    interface Relation extends Partial {
        String getSender();
        String getReceiver();
    }

    // Now this interface can not be created by himself, so it depends from the relationship
    interface Force {
        @Nullable String getIssuer();
        boolean isAlerted();
    }

    // We will define here a Relationship + Forcing interface as a full creation model (As long as Relation extends PartialModel)
    interface Creation extends Relation, Force {}

    // The complete interface will carry out the Creation relationship and the default model holders.
    interface Complete extends Model, Creation {}

}

Creating the final model concatenation

Now, to have everything in a much more understandable way, we are going to create a class that extends the final Complete and has the annotations that we talked about before.

@ModelProperties.RouteKey("friends")
@ModelProperties.Cache
public interface Friendship extends FriendshipDoc.Complete {}

So that's everything for now. You do not need to always follow this schema as long as you have a small amount of properties or create derivations. But you can use it always you have a complicated model that must be understood very delicately by other developers.

Clone this wiki locally