[MUSIC PLAYING]
GARIMA JAIN: Hi, I'm Garima Jain from India.
I work for GoDaddy Studio as a principal Android engineer,
and I'm also a Google Developer Expert in Android.
As part of the MAD Skills series on Architecture,
I wanted to share a tip about creating separate data
models based on various architectural layers
in your project.
We'll be calling these data models entities.
Here goes my tip.
I suggest creating one or more separate entities earlier
in the project for a clean and scalable model architecture.
The reason for this is, different layers in the app
have different responsibilities.
For a given type of data, each layer
will most likely need layer-specific attributes
to perform its stats.
Examples of such entities are a remote user entity
at the data layer and a user UI state entity at the UI layer.
Assuming that your project is divided
into these layers, as suggested in the guide to app
architecture, ideally each layer in the project
should have one or more unique entities.
And here's how separating entities
works out best in my experience.
First, remote entities.
These are entities defined to represent
the JSON response coming in from server or network API.
Database entities.
These represent database entities
fresh from the database if a database
is present in your project.
Domain entities.
If a domain layer is present in your project,
then these are your business models.
UIState entities.
Your state model for screen.
And additionally, mapper classes to map
between various entities.
This is optional.
Now to understand this better, we
will touch upon various advantages of doing this.
And in order to do that, we will start with an example.
Let's say that the response we're getting from server
looks like this.
This is an example of remote API entity
that we have created for user response.
We have a user object, which has its own ID, user name, token,
inventory, and profile, along with some additional data
that we have omitted for the purpose of this video.
Here's how the profile object looks
like, with some mixed casing coming
in from the server-- for example,
profile image URL field.
We use @SerializeName to map it to camel case filenames.
And here's how the inventory list looks like.
Within the response, there is a list of inventory items
which each can have its own ID, name, et cetera.
Now, if you want to try to save the user object to database
like room directly, without mapping it to a new entity,
here's how our database entity would look like.
Let's say that we do not want to possess
the token database since we want to store it somewhere securely.
So we add annotation Ignore to it.
We also do not want to save inventory object
as part of user object, since it will be a separate room entity.
We also do not want to put this user profile to database
yet, since it is not used within our app,
so we add an ad [INAUDIBLE] Ignore
annotation to it as well.
This approach clutters our database entity
and could cause confusion.
So we should create a separate entity in such cases.
Here's how our converted database entity looks like,
which contains just the data we need.
Doesn't it look cleaner?
So advantages of data entities.
All the entities contain just the required data.
The remote entities could have extra objects,
which need not be persisted.
So say goodbye to add the date Ignore annotations,
within your database entities now.
Now let's create a domain entity for the user's inventory
object.
By creating domain entities, one could write business rules
and separate these rules into different modules, which could
even be pure Kotlin modules.
These have the benefits of potentially improving
build times and being able to share entities
across multiple platforms.
This step is optional and can be decided on a project
to project basis.
One could also create this same entity as a UI entity
instead within our UI layer.
Now let's say that we want to parse the inventory
object from one screen to another in Android.
We will need the ID to fetch the details of the inventory item
from the server, and we need its name to be shown in the toolbar
while we're fetching the details from the server.
By having a separate domain or UI entity,
while passing data from one screen to another,
we can add our personalized annotation to it
and send only limited data and need not bug the parce labels.
Send only what you need to, since there
is a limit to the amount of data that can be parced.
Now let's look at an example of where creating UI entities
is quite helpful.
We want to show user inventory as a list,
and the user can select one inventory item out of those.
In such cases, creating a separate UI state
has various advantages.
UI entity could have a state-related data,
for example, from a list of available inventory,
a single inventory is selected at a time.
So we could keep a selected volume within the UI state.
By having a UI state for a recyclable list item
could also help with efficient [? defense ?] with just
the data we need.
You can see how creating different entities
in different parts of the code base
can have several advantages.
Apart from these, the app becomes much more maintainable,
because if you want to swap out a remote API with another one,
in such cases, the changes remain limited to just the API
layer and everything else remains the same.
Also, if there are UI changes, only the UI layer
needs to know about such changes,
and again, the rest, everything remains the same.
While there are so many advantages, just
like two sides of a coin, there are certain disadvantages
to this as well, such as first creating and maintaining
these entities could add to development time.
Having multiple entities could cause confusion
among developers on which entity to use.
Mapping between different entities
to pass them around all the time could get cumbersome.
And the [INAUDIBLE] such layering could be overwhelming
and might not be beneficial for small-scale projects,
but for large-scale projects, this type of layering
has always proved to be super helpful in my experience.
For such projects, in order to mitigate these disadvantages,
it is beneficial to document and standardize such approaches
and rules with the team so that the whole team
can adopt similar naming convention and rules
about separating such entities.
Apart from that, since different entities
provide different advantages, use the ones
that might benefit you the most.
I think these are still the minimum ones that should
be separated out in a project.
Add the data layer, remote entity, and a database entity,
if there is a database in your project.
UI state and the UI layer are a domain entity as well,
if domain is present.
So happy separating.
This was my tip about clean and scalable entities.
Hope you enjoyed it and will apply it in your next project.
Coming up next on this MAD skill series
is a live Q&A on Thursday, where the Android team answers all
your questions on architecture.
You can ask your questions now using #AskAndroid on Twitter.
Bye.
Thank you.
[MUSIC PLAYING]