今天我們先定義好資料夾結構,然後寫一些框和範例起來,首先先建立下面的資料夾路徑&檔案
當收到Linebot的請求後,我們的應用會在Router層接收並處理它,根據request的不同,Router層能夠調用不同的服務(service)來進行處理。Service的負責統一調用Adapter層和Domain層。Adapter負責與外部資源進行互動和操作,而Domain層則專注於處理業務邏輯。
我們把前幾天寫的dynamodb放到adapter下,然後在dynamodb下建立interface.go,把我們寫好想要對外(自己的service)提供的function放進去
// interface.go
package dynamodb
import (
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
)
type DynamodbI interface {
CreateGoogleOAuthTable() (*types.TableDescription, error)
AddGoogleOAuthToken(tok GoogleOAuthToken) error
TxUpdateGoogleOAuthToken(tok GoogleOAuthToken) (*dynamodb.TransactWriteItemsOutput, error)
GetGoogleOAuthToken(line_userid string) (GoogleOAuthToken, error)
}
接著我們在app/service下,建立一個Sample service資料夾,和interface.go,sample_service.go,service.go三個檔案
假設我們這個service想要使用上面dynamodb提供的GetGoogleOAuthToken()
,我們就在interface.go像下面這樣加上去
// interface.go
package sample
import "github.com/onepiece010938/Line2GoogleDriveBot/internal/adapter/dynamodb"
type SampleServiceDynamodbI interface {
GetGoogleOAuthToken(line_userid string) (dynamodb.GoogleOAuthToken, error)
}
接著service.go,創建一個 SampleService
服務,並透過構造函數 NewSampleService()
將其所依賴的 SampleServiceDynamodb
實例注入到服務中。
package sample
import "context"
type SampleService struct {
sampleServiceDynamodb SampleServiceDynamodbI
}
// SampleServiceParam 是用於建構 SampleService 的參數結構體
type SampleServiceParam struct {
SampleServiceDynamodb SampleServiceDynamodbI
}
// 建立並回傳一個新的 SampleService 實例
// param: SampleService 的建構參數,包含一個 SampleServiceDynamodb 實例
func NewSampleService(_ context.Context, param SampleServiceParam) *SampleService {
return &SampleService{
sampleServiceDynamodb: param.SampleServiceDynamodb,
}
}
在測試or要替換掉Dynamodb的時候,只需更改NewSampleService
的參數就好,而不用去動到SampleService
本身的程式。
最後sample_service.go就是我們服務本身提供的function,這邊寫一個簡單的範例,直接去調用注入進來的GetGoogleOAuthToken
,輸入lineID查詢取得token後回傳PK,也就是輸入lineID test1234
如果有查到token會回傳LINE#test1234
。
package sample
import (
"context"
"fmt"
)
func (s *SampleService) Sample(ctx context.Context, lineID string) (string, error) {
t, err := s.sampleServiceDynamodb.GetGoogleOAuthToken(lineID)
if err != nil {
return "", err
}
fmt.Println(t)
return t.PK, nil
}
最後的最後到application.go,他負責把所有的service拉起來。因此後續有新的service時,我們也會放到Application這個srtuct裡,同時還有一個*linebot.Client供整個application來調用linebot。
package app
import (
"context"
"github.com/line/line-bot-sdk-go/linebot"
"github.com/onepiece010938/Line2GoogleDriveBot/internal/adapter/dynamodb"
serviceSample "github.com/onepiece010938/Line2GoogleDriveBot/internal/app/service/sample"
)
type Application struct {
SampleService *serviceSample.SampleService
LineBotClient *linebot.Client
}
// 建立並回傳一個新的 Application 實例
// dynamodb: 輸入實現了 dynamodb.DynamodbI interface的對象
func NewApplication(ctx context.Context, dynamodb dynamodb.DynamodbI, lineBotClient *linebot.Client) *Application {
app := &Application{
LineBotClient: lineBotClient,
SampleService: serviceSample.NewSampleService(ctx, serviceSample.SampleServiceParam{
SampleServiceDynamodb: dynamodb, // 在這邊傳入DynamoDB的instance
}),
}
return app
}
這樣今天就完成了應用層的建立,並寫了一個sample service當作範例,明天我們來寫Router層的部分,那我們明天見囉~