網頁

2023/9/4

Golang 架構分層間的資料傳遞

以Go語言表示架構外層(outer layer)與內層(inner layer)的資料傳遞。


本篇是在看簡潔架構(The Clean Architecture)的依賴原則(Dependency Rule)時,以及參考The Clean Architecture — Beginner’s Guides這篇文章後,試著用Go來實現一般依賴、介面隔離和依賴反轉,以及層與層之間資料傳輸物件的擺放位置。

資料傳輸物件要定義在被依賴的那層。

內層為Inner,外層調用其方法時,透過輸入參數InnerInput和輸出參數InnerOutput與外層溝通。輸出/輸入參數即為無操作行為的資料傳輸物件(DTO(Data Transfer Object))。

inner/inner.go

package inner

type Inner struct {
}

type InnerInput struct {
    Id string
}

type InnerOutput struct {
    Id string
}

func (inner Inner) Do(input InnerInput) InnerOutput {
    return InnerOutput{
        Id: input.Id,
    }
}

外層為Outer,其依賴內層Inner,透過內層的輸入參數InnerInput和輸出參數InnerOutput來調用內層的方法。

同樣地,外層也有與外界溝通的輸入參數OuterInput和輸出參數OuterOutput

outer/outer.go

package outer

import "abc.com/demo/inner"

type Outer struct {
    inner inner.Inner
}

type OuterInput struct {
    Id string
}

type OuterOutput struct {
    Id string
}

func (outer Outer) Do(input OuterInput) OuterOutput {
    innerOutput := outer.inner.Do(
        inner.InnerInput{
            Id: input.Id,
        },
    )
    return OuterOutput{
        Id: innerOutput.Id,
    }
}

外層物件依賴內層物件,所以外層為依賴方、內層為被依賴方,所以外層與內層溝通用的資料傳輸物件是定義在內層。


介面隔離、依賴反轉

透過在外層定義介面並讓內層實作該介面,將原本外層依賴內層的關係反轉為內層依賴外層,即依賴反轉。

定義外層使用內層的介面Inner和方法簽章。

outer/interface.go

package outer

type InnerInput struct {
    Id string
}

type InnerOutput struct {
    Id string
}

type Inner interface {
    Do(input InnerInput) InnerOutput
}

把外層原本依賴的內層改為依賴外層自己的介面,則從此外層不再依賴於內層。

outer/outer.go

package outer

type Outer struct {
    inner Inner
}

type OuterInput struct {
    Id string
}

type OuterOutput struct {
    Id string
}

func (outer Outer) Do(input OuterInput) OuterOutput {
    innerOutput := outer.inner.Do(
        InnerInput{
            Id: input.Id,
        },
    )
    return OuterOutput{
        Id: innerOutput.Id,
    }
}

內層實作外層介面,也就是內層變成依賴於外層。

inner/inner.go

package inner

import "abc.com/demo/outer"

type Inner struct {
}

type InnerInput struct {
    Id string
}

type InnerOutput struct {
    Id string
}

func (inner Inner) Do(input outer.InnerInput) outer.InnerOutput {
    return outer.InnerOutput{
        Id: input.Id,
    }
}


沒有留言:

張貼留言