programming

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.

package usecase

import (
	"context"

	"github.com/santekno/learn-golang-restful/models"
)

type ArticleUsecase interface {
	GetAll(ctx context.Context) ([]models.ArticleResponse, error)
	GetByID(ctx context.Context, id int64) (models.ArticleResponse, error)
	Update(ctx context.Context, article models.ArticleUpdateRequest) (models.ArticleResponse, error)
	Store(ctx context.Context, article models.ArticleCreateRequest) (models.ArticleResponse, error)
	Delete(ctx context.Context, id int64) (bool, error)
}

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.

type Usecase struct {
	articleRepository repository.ArticleRepository
}

func New(repo repository.ArticleRepository) *Usecase {
	return &Usecase{articleRepository:repo}
}

Followed by adding the GetAll() function with the process in which there is access to the repository that we have defined.

func (u *Usecase) GetAll(ctx context.Context) ([]models.ArticleResponse, error) {
	var response []models.ArticleResponse

	res, err := u.articleRepository.GetAll(ctx)
	if err != nil {
		return response, err
	}

	for _, v := range res {
		response = append(response, v.ToArticleResponse())
	}

	return response, nil
}

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.

type ArticleListResponse struct {
	HeaderResponse
	ArticleResponse data []ArticleResponse
}

type ArticleResponse struct {
	ID int64
	Title string
	Content string
	CreateAt time.Time
	UpdateAt time.Time
}

type HeaderResponse struct {
	Code int
	Status string
}

Usecase Function Retrieving Article ByID Data

The next process is to add a function to the usecase like this.

func (u *Usecase) GetByID(ctx context.Context, id int64) (models.ArticleResponse, error) {
	var response models.ArticleResponse

	res, err := u.articleRepository.GetByID(ctx, id)
	if err != nil {
		return response, err
	}

	response = res.ToArticleResponse()
	return response, nil
}

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.

func (u *Usecase) Update(ctx context.Context, request models.ArticleUpdateRequest) (models.ArticleResponse, error) {
	var article = new(models.Article)
	var response models.ArticleResponse

	if request.ID == 0 {
		return response, error.New("request article_id jangan nol atau kosong")
	}

	// validasi data dari database ditemukan
	article, err := u.articleRepository.GetByID(ctx, request.ID)
	if err != nil {
		kembalikan respons, err
	}

	if article.ID == 0 {
		return response, err.New("data tidak ditemukan")
	}

	// dari permintaan ke struktur artikel
	article.FromUpdateRequest(request)

	// mengeksekusi pembaruan
	article, err = u.articleRepository.Update(ctx, article)
	if err != nil {
		kembalikan respons, err
	}

	// menambahkan pembaruan data ke respons
	response = article.ToArticleResponse()
	return response, nil
}

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.

func (u *Usecase) Store(ctx context.Context, request models.ArticleCreateRequest) (models.ArticleResponse, error) {
	var article = new(models.Article)
	var response models.ArticleResponse

	// mengubah permintaan menjadi struktur artikel
	article.FromCreateRequest(request)

	// penyimpanan yang dieksekusi
	articleID, err := u.articleRepository.Store(ctx, article)
	if err != nil {
		kembalikan respons, err
	}

	article.ID = articleID
	response = article.ToArticleResponse()
	return response, nihil
}

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.

func (u *Usecase) Delete(ctx context.Context, id int64) (bool, error) {
	var isSuccss bool

	// memvalidasi data dari basis data ditemukan
	article, err := u.articleRepository.GetByID(ctx, id)
	if err != nil {
		return isSuccss, err
	}

	if artikel == nil {
		return isSuccss, err.New("artikel tidak ditemukan")
	}

	isSuccss, err = u.articleRepository.Delete(ctx, id)
	if err != nil {
		return isSuccss, err
	}

	return isSuccss, nil
}
comments powered by Disqus