06 Creating Usecases as Data Logic
This time we will continue the project of making this RESTFul API by creating a Usecase function. Previously it was discussed that this Usecase Layer will contain logic data or data processing which is used some logic needed in a process.
For example, the usecase for converting article data into the latest data from a user request. Then in this usecase layer we will create process logic such as: a. Checking the article_id request is not empty b. Checking that the article_id in the database is already available c. The process of changing the data requested by the user d. Handling process if an error occurs in the database
At least the above process will be implemented in one of the functions in the usecase layer.
Usecase Interface Creation
First, we need to create a file name usecase.go in the usecase folder then fill the file like this.
1package usecase
2
3import (
4 "context"
5
6 "github.com/santekno/learn-golang-restful/models"
7)
8
9type ArticleUsecase interface {
10 GetAll(ctx context.Context) ([]models.ArticleResponse, error)
11 GetByID(ctx context.Context, id int64) (models.ArticleResponse, error)
12 Update(ctx context.Context, article models.ArticleUpdateRequest) (models.ArticleResponse, error)
13 Store(ctx context.Context, article models.ArticleCreateRequest) (models.ArticleResponse, error)
14 Delete(ctx context.Context, id int64) (bool, error)
15}In the code above interface which can later be communicated for use in the delivery layer. And the functions that have been defined above will be implemented one by one.
Usecase Function Retrieve All Article Data
In this usecase, we will try to make the implementation of the interface above into an implement function. Previously we need to create a file in the usecase folder article/article.go and first initialize this usecase with the code as below.
1type Usecase struct {
2 articleRepository repository.ArticleRepository
3}
4
5func New(repo repository.ArticleRepository) *Usecase {
6 return &Usecase{articleRepository:repo}
7}Followed by adding the GetAll() function with the process in which there is access to the repository that we have defined.
1func (u *Usecase) GetAll(ctx context.Context) ([]models.ArticleResponse, error) {
2 var response []models.ArticleResponse
3
4 res, err := u.articleRepository.GetAll(ctx)
5 if err != nil {
6 return response, err
7 }
8
9 for _, v := range res {
10 response = append(response, v.ToArticleResponse())
11 }
12
13 return response, nil
14}We can see, in this usecase there is a new struct that stores the repository layer data into the usecase layer struct. So it is very important that we distinguish the struct so that the data retrieved into the database does not all appear and only a few fields are displayed to the user according to their needs.
For example, let’s say password, this is very crucial if we directly return it to the user then we will see all the passwords that exist for each user.
So, we need to create an article_web.go file to hold the struct request and response from each usecase we create.
1type ArticleListResponse struct {
2 HeaderResponse
3 ArticleResponse data []ArticleResponse
4}
5
6type ArticleResponse struct {
7 ID int64
8 Title string
9 Content string
10 CreateAt time.Time
11 UpdateAt time.Time
12}
13
14type HeaderResponse struct {
15 Code int
16 Status string
17}Usecase Function Retrieving Article ByID Data
The next process is to add a function to the usecase like this.
1func (u *Usecase) GetByID(ctx context.Context, id int64) (models.ArticleResponse, error) {
2 var response models.ArticleResponse
3
4 res, err := u.articleRepository.GetByID(ctx, id)
5 if err != nil {
6 return response, err
7 }
8
9 response = res.ToArticleResponse()
10 return response, nil
11}Article Data Update Function Usecase
As mentioned above, the usecase to update the data has a relatively long process logic than the process logic of other functions so we can see below.
1func (u *Usecase) Update(ctx context.Context, request models.ArticleUpdateRequest) (models.ArticleResponse, error) {
2 var article = new(models.Article)
3 var response models.ArticleResponse
4
5 if request.ID == 0 {
6 return response, error.New("request article_id jangan nol atau kosong")
7 }
8
9 // validasi data dari database ditemukan
10 article, err := u.articleRepository.GetByID(ctx, request.ID)
11 if err != nil {
12 kembalikan respons, err
13 }
14
15 if article.ID == 0 {
16 return response, err.New("data tidak ditemukan")
17 }
18
19 // dari permintaan ke struktur artikel
20 article.FromUpdateRequest(request)
21
22 // mengeksekusi pembaruan
23 article, err = u.articleRepository.Update(ctx, article)
24 if err != nil {
25 kembalikan respons, err
26 }
27
28 // menambahkan pembaruan data ke respons
29 response = article.ToArticleResponse()
30 return response, nil
31}Ada beberapa pengecekan jika kita lihat di proses untuk pengubahan data tersebut.
Kode Sumber 4.4. ## Usecase Fungsi Tambah Data Artikel Pada proses usecase untuk tambah data seperti di bawah ini.
1func (u *Usecase) Store(ctx context.Context, request models.ArticleCreateRequest) (models.ArticleResponse, error) {
2 var article = new(models.Article)
3 var response models.ArticleResponse
4
5 // mengubah permintaan menjadi struktur artikel
6 article.FromCreateRequest(request)
7
8 // penyimpanan yang dieksekusi
9 articleID, err := u.articleRepository.Store(ctx, article)
10 if err != nil {
11 kembalikan respons, err
12 }
13
14 article.ID = articleID
15 response = article.ToArticleResponse()
16 return response, nihil
17}Kode Sumber 4.4. ## Usecase Fungsi Hapus Data Artikel Pada proses usecase hapus data dapat kita lihat ada proses ketika kita melakukan pengecekan terlebih dahulu ke dalam database apakah id tersebut ada atau tidak, jika ada akan dilanjutkan untuk melakukan proses hapus tetapi ketika tidak ditemukan akan muncul error.
1func (u *Usecase) Delete(ctx context.Context, id int64) (bool, error) {
2 var isSuccss bool
3
4 // memvalidasi data dari basis data ditemukan
5 article, err := u.articleRepository.GetByID(ctx, id)
6 if err != nil {
7 return isSuccss, err
8 }
9
10 if artikel == nil {
11 return isSuccss, err.New("artikel tidak ditemukan")
12 }
13
14 isSuccss, err = u.articleRepository.Delete(ctx, id)
15 if err != nil {
16 return isSuccss, err
17 }
18
19 return isSuccss, nil
20}