Golang 事务性 API 设计

您所在的位置:网站首页 imagewriter Golang 事务性 API 设计

Golang 事务性 API 设计

#Golang 事务性 API 设计| 来源: 网络整理| 查看: 265

我正在尝试使用 Go 遵循Clean Architecture。该应用程序是一个简单的图像管理应用程序。

我想知道如何最好地为我的存储库层设计接口。我不想将所有存储库方法组合到一个大接口中,就像我发现的一些示例那样,我认为在 Go 中通常首选小接口。我不认为有关管理图像的用例代码需要知道存储库还存储用户。所以我想有UserReader,UserWriter和ImageReader。ImageWriter复杂的是代码需要是事务性的。事务管理属于 Clean Architecture 存在一些争论,但我认为用例层需要能够控制事务。我认为,属于单个事务的是业务规则,而不是技术细节。

现在的问题是,如何构造接口?

功能方法

所以在这种方法中,我打开一个事务,运行提供的函数并在没有错误的情况下提交。

type UserRepository interface {

    func ReadTransaction(txFn func (UserReader) error) error

    func WriteTransaction(txFn func (UserWriter) error) error

}

type ImageRepository interface {

    func ReadTransaction(txFn func (ImageReader) error) error

    func WriteTransaction(txFn func (ImageWriter) error) error

}

问题:不,我不能在单个事务中轻松地编写用户和图像,我必须UserImageRepository为此创建一个额外的接口并提供一个单独的实现。

事务作为存储库

type ImageRepository interface {

    func Writer() ImageReadWriter

    func Reader() ImageReader

}

我认为这与功能方法非常相似。它不会解决联合使用多个存储库的问题,但至少可以通过编写一个简单的包装器来实现。

一个实现可能是这样的:

type BoltDBRepository struct {}

type BoltDBTransaction struct { *bolt.Tx }

func (tx *BoltDBTransaction) WriteImage(i usecase.Image) error

func (tx *BoltDBTransaction) WriteUser(i usecase.User) error

....

不幸的是,如果我实现这样的交易方法:

func (r *BoltDBRepository) Writer() *BoltDBTransaction

func (r *BoltDBRepository) Reader() *BoltDBTransaction

因为这没有实现ImageRepository接口,所以我需要一个简单的包装器

type ImageRepository struct { *BoltDBRepository }

func (ir *ImageRepository) Writer() usecase.ImageReadWriter

func (ir *ImageRepository) Reader() usecase.ImageReader

作为价值的交易

type ImageReader interface {

    func WriteImage(tx Transaction, i Image) error

}

type Transaction interface { 

    func Commit() error

}

type Repository interface {

    func BeginTransaction() (Transaction, error)

}

存储库实现看起来像这样

type BoltDBRepository struct {}

type BoltDBTransaction struct { *bolt.Tx }

// implement ImageWriter

func (repo *BoltDBRepository) WriteImage(tx usecase.Transaction, img usecase.Image) error {

  boltTx := tx.(*BoltDBTransaction)

  ...

}

问题:虽然这可行,但我必须在每个存储库方法的开头键入断言,这看起来有点乏味。

所以这些是我可以想出的方法。哪个最合适,或者有更好的解决方案?



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3