9KicksXCUmart / 9Kicks-Mircoservices-Kotlin

0 stars 0 forks source link

9Kicks Microservices Kotlin

This is one of the microservices for the 9Kicks project. It is written in Kotlin and uses the Spring Boot framework.

Implemented features:

Prerequisites

1. Getting Started

1.1 Local AWS Environment

Install AWS CLI and use aws configure command to configure your aws.

Below are the settings for this project:

AWS Access Key ID: <YOUR-ACCESS-KEY>
AWS Secret Access Key: <YOUR-SECRET-ACCESS-KEY>
Default region name: ap-southeast-1
Default output format: json

1.2. Alternate Env Variable with IntelliJ

In case you want to use another IntelliJ for development or use another pair of Access Key and Secret Key. You can add the following environment variable in IntelliJ.

AWS_ACCESS_KEY_ID=<YOUR-ACCESS-KEY>;
AWS_SECRET_ACCESS_KEY=<YOUR-SECRET-ACCESS-KEY>;
AWS_DYNAMODB_TABLE_NAME=<DYNAMODB-TABLE-NAME>;
CORS_ORIGINS=<FRONTEND-URL-HOST>;
STRIPE_KEY=<YOUR-STRIPE-KEY>;
GO_BACKEND_URL=<BACKEND-GO-URL-HOST>

1.3. Alternate Env Variable with .env

In case you want to use .env for development or use another pair of Access Key and Secret Key. You can add the following environment variable.

cp .env.example .env

Input your credentials in the .env file.

AWS_ACCESS_KEY_ID=<YOUR-ACCESS-KEY>
AWS_SECRET_ACCESS_KEY=<YOUR-SECRET-ACCESS-KEY>
AWS_DYNAMODB_TABLE_NAME=<DYNAMODB-TABLE-NAME>
CORS_ORIGINS=<FRONTEND-URL-HOST>
STRIPE_KEY=<YOUR-STRIPE-KEY>
GO_BACKEND_URL=<BACKEND-GO-URL-HOST>

Build and Run Spring Boot:

make

2. Coding Standard

2.1 Camel Case

For any variable, function naming we use Camel Case
e.g. demoVar, demoFunc()

2.2 Constructor Dependency Injection

For any dependency injection in Kotlin Spring Boot, we will use constructor dependency injection

class DemoController(
    private val demoController: DemoRepositoryImpl
    ) {
    fun demo(){ }
}

2.3 MVC Design Pattern

The project will be based on 4 major components

Controller Define all API endpoints
Service Perform all the business logic
Repository Perform all pure CRUD
Model Define all Class

2.4 CRUD Naming

For any CRUD operations, it must follow the following naming:

Operation Naming Example
Create add<Object>() addUser()
Read get<Object>() getUser()
Update update<Object>() updateUser()
Delete delete<Object>() deleteUser()

2.5 get() and find()

For any function name in Service Layer, we will use find(). e.g. fun findUserById()
For any function name in Repository Layer, we will use get(). e.g. fun getUserById()

2.6 API Endpoint Naming

For any API we follow the following standard /api/v1/<controller-name>/<resources>
e.g./api/v1/account-summary/user-details

2.6.1 Hyphenation

For any API we use hyphen - to separate words
e.g./api/v1/account-summary/user-details

2.6.2 s and without s

For any API that retrieves only 1 resource, we use singular form to indicate
e.g./api/v1/user/<user-id>

For any API that retrieves more than 1 resources, we use plural form, s, to indicate
e.g./api/v1/users

2.7 all and without all

For any functions that retrieve 1 object only, we use singular form
e.g. getUser()

For any functions that retrieve more than 1 object, we use plural form
e.g. getAllUsers()

2.8 Kotlin Data Class

For any model class/object, we will use Kotlin Data Class to construct

Non-Nested Class

data class Person(
    val age: Int,
    val height: Int
)

Nested Class

data class Person(
    val age: Int,
    val detail: Detail
) {
    data class Detail(
        val height: Int,
        val weight: Int
    )
}

2.9 Data Transfer Object

For any object that we receive from remote calls (backend, frontend, database), we create a DTO object for it.
Beware: It is different from the main model class UserDTO != User

For example:
We want to send an User object from backend to frontend - Account Summary.
We define a UserDTO:

data class UserDTO(
    val age: Int
)

It encapsulates some data that frontend - Account Summary does not need to know, e.g. creditCardNumber

2.10 Request and Response

For any object that is received as a response. We use place response after the object name.
e.g. UserResponse

For any object that is being sent as a request. We use place request after the object name.
e.g. UserRequest