Definition of a Model
A model represents a core concept within a system, not merely a one-to-one mapping to a database table. While models often correspond to tables, they primarily encapsulate domain concepts and related behavior.
Models as Domain Components
Different conceptual roles (e.g., admin, customer, employee) may share a single database table but represent distinct system components. Models should reflect these conceptual differences rather than just database structure.
Encapsulation of Data Access
All data retrieval and persistence operations must go through the model layer. Functions such as finding or creating users are defined within the models package to centralize database interaction.
Business Logic in Models
The model layer enforces business rules related to data shape and validation, such as field length constraints. This ensures that all created or retrieved data adheres to defined domain rules.
Using Types to Enforce Roles
Instead of relying solely on flags (e.g., isAdmin), distinct types like Admin can be introduced. Strong typing enforces clearer boundaries and makes role-specific operations explicit.
Business Logic vs. Application Logic
Business logic governs data constraints and structure, while application logic defines what actions users can perform. Application-level rules (e.g., only admins can delete users) belong in controllers or service layers, not in models.
Example: Article Model
A simple Article model is defined with fields such as ID, title, and content. Functions to retrieve all articles or a specific article are implemented, initially returning dummy data to simulate future database interaction.
All right what is a model? If you have ever worked with something like Laravel or Rails or Django
you might say that it corresponds to a table in the database. Now even though that there is often
a one-to-one representation between a model and a database table it's not the complete mental model.
You should think of a model as these core components slash concepts of our systems.
Let's say we have a bank as we did in the previous module. We will have the concept of a user. Now a
user can be many things. It can be an admin, a customer, an employee, an employee and a customer.
These might all be represented by one database table called users but conceptually there is a
huge difference between an admin user and a customer.
Now this is a for-all example. In production you might actually have different tables but technically
they could all be part of the same table but conceptually be different components in the
overall system. So let's take a quick example and look at how we can illustrate this in code.
Say we have this user model so type user struct
id int64 name is going to be a string. Now the only way you should be able to retrieve a user from
the database should be through the models package or through the models layer. So we need to define
some some functions to to retrieve users. So let's say we have a function here called find user
that takes in a context.context and then an id of an int64. It returns a function to find a user.
So let's say we have a function here called find user that takes in a context.context and then an id of an int64. It returns a function to find a user.
So let's say we have a function here called find user that takes in a context.context and then an id of an int64. It returns a function to find a user.
So let's say we have a function here called find user that takes in a context.context and then an id of an int64. It returns a function to find a user.
So let's say we have a function here called find user that takes in a context.context and then an id of an int64. It returns a function to find a user.
Right and then we would have the actual logic for curing the database. And then let's just return a dummy user. Let me say id is one name is just going to be my name for now. More than all right and then also an error.
All right and then also an error.
I'm omitting the logic for for actually retrieving elements out of the database because we will hook this up in the next in the next module for now I just want to illustrate the concepts same thing goes for creating a new user this would also have to be done in this in this package so we can create a new function here from new user and we will say again let's take in a context.context and then an id of an int64. It returns a function to find a user that takes in a context.context and then an id of an int64. It returns a function to find a user.
name you return the created user or we return an error and again you will have
actual logic for inserting user here and now let's just return a dummy user once
more saying the ID that's gonna be true name is gonna be the name we provided to
the function and then we return no again all logic for fetching and inserting
users now models in general go through this package which also mean that any
validation logic or business logic needs to be defined within this this package
or this layer of our architecture so here we would say
let's say we can't have a name that is an empty string and you can also not
have a name that is less than one character and we can also not have a
name that is longer than 50 characters and if any of these cases returns true
we're just gonna say return empty user struct and say errors new user
name invalid must be longer than one character and less than 50 characters so
let me just go give that a save and now the validation logic so we ensure that we can only
create a user through this package and the only way to create a user is through this function
which has all of the business logic that defines the shape of the data now say we
wanted to have admins in our system that can perform certain actions that a normal
user cannot we could include is admin field on our users table and then add it
to the user model so do something like is admin right and then we would check that field before
letting the user perform those guarded actions however go is a strictly typed
language so we should rely on that instead to to enforce data being correct
so let's say we have added this field now we can instead introduce or an admin
model that will simply be be one-to-one like this like the user but this is a distinct type and then we
can go down here and we can say grab all of this and say find admin and
instead of returning our user we will save return as an admin ads men let's
just return the ID we provided here let's see I don't know let's just say Bob is the
admin for now so that we would have to be very explicit both what you're asking for but also
for the distinct type that we get them back and then we can use this this admin
structs as an input to those those operation or those actions that would
need admin level permissions I hope this illustrates that the concept of a model
goes further than just mapping to a database table will continuously add
models as we progress through the course so
hopefully by the end you will have solidified the concept it's important to
note that we do not handle application logic in the model layer only business
logic but what's the difference business logic for example relates to the shape
of the data like how the name of a user had to be a certain length it could also
be how how long our password should be or which character it should contain
so we can use this as an example of what we can do with this application logic however will be more related to what operations a user can do it's not limited to that but it's a good example of what is application logic so deleting a user would have to be done by an admin which is application logic rather than business logic I hope this
illustrates the concept of a model and that it goes further than just being a
one-to-one mapping with a database table we will continuously add models through
the for the for the cause so hopefully that will solidify the concept for you
it's important to note that we do not handle application logic in the model
layer only business logic but what is the difference business logic for example
is the shape of our data so like the length of the name that we just had or a
password application logic however will be what operations a user could do so
take our user and admin models as an example right you could have some logic
that says only an admin can create or delete a user which will be an example
of application logic this does not go into the layer model the model layer
sorry and you would typically see this in the controller layer or maybe in a
service service layer these two concepts does run very closely together so it can
take some time to to understand the finer details but a general rule of form
is that if it relates to data then it's business logic and if it relates to
how an application functions is application logic now let's start by
defining a very simple version of our article model and we're going to start
by creating a struct called article and then we're going to say ID is going to
be an int64 it's going to be title string and we're going to have I can't spell string
then we're going to have content also going to be a string and then for now we need two functions one
to return all articles and one that returns a specific article we will start by just returning
some dummy data as we haven't covered how to interact with a real database yet so let's
start by creating the dummy articles so we're going to say bar article article one
of article struct and ID is going to be one let's say title is sample article
and content will be this is a sample article
all right let's copy paste all of this and say article two ID two and say another
another sample article and this is also this is another sample article great then
let's define the the model function that returns all the articles because that is simply going to
be find find articles and we're just going to accept a context here because we're going to
need that for later and we're going to return a slice of article or an error again we are mimicking
the real thing here where for now we could just return the article right but when we get to the
database we will also return an error and here we're simply going to say the article slice
and we will return article one and article two and then nil and then we import the context
now for the find articles we can copy paste this it's going to be find article and we're
going to return one and we will then need to specify what article we're looking for we're
going to be using the ID here so we're going to say ID it's 64. and then we're just going to use
the switch statement for now say ID and if you have case an article one and then also article two
then we just return those articles let's go on now
and then article two and if we can't match anything we just say article nil we could technically say
something like I was new here but it doesn't really matter this is just dummy data and there
we have it so this is our our article model for now so we can actually start to put something on