本文次要赏析一下go-bank-transfer对于Clean Architecture的实际

我的项目构造

├── adapter│   ├── api│   │   ├── action│   │   ├── logging│   │   ├── middleware│   │   └── response│   ├── logger│   ├── presenter│   ├── repository│   └── validator├── domain├── infrastructure│   ├── database│   ├── log│   ├── router│   └── validation└── usecase
这里分为adapter、domain、infrastructure、usecase四层

domain

account

type AccountID stringfunc (a AccountID) String() string {    return string(a)}type (    AccountRepository interface {        Create(context.Context, Account) (Account, error)        UpdateBalance(context.Context, AccountID, Money) error        FindAll(context.Context) ([]Account, error)        FindByID(context.Context, AccountID) (Account, error)        FindBalance(context.Context, AccountID) (Account, error)    }    Account struct {        id        AccountID        name      string        cpf       string        balance   Money        createdAt time.Time    })func NewAccount(ID AccountID, name, CPF string, balance Money, createdAt time.Time) Account {    return Account{        id:        ID,        name:      name,        cpf:       CPF,        balance:   balance,        createdAt: createdAt,    }}func (a *Account) Deposit(amount Money) {    a.balance += amount}func (a *Account) Withdraw(amount Money) error {    if a.balance < amount {        return ErrInsufficientBalance    }    a.balance -= amount    return nil}func (a Account) ID() AccountID {    return a.id}func (a Account) Name() string {    return a.name}func (a Account) CPF() string {    return a.cpf}func (a Account) Balance() Money {    return a.balance}func (a Account) CreatedAt() time.Time {    return a.createdAt}func NewAccountBalance(balance Money) Account {    return Account{balance: balance}}
account定义了AccountRepository接口及Account类型,同时还提供了Withdraw、Deposit办法

transfer

type TransferID stringfunc (t TransferID) String() string {    return string(t)}type (    TransferRepository interface {        Create(context.Context, Transfer) (Transfer, error)        FindAll(context.Context) ([]Transfer, error)        WithTransaction(context.Context, func(context.Context) error) error    }    Transfer struct {        id                   TransferID        accountOriginID      AccountID        accountDestinationID AccountID        amount               Money        createdAt            time.Time    })func NewTransfer(    ID TransferID,    accountOriginID AccountID,    accountDestinationID AccountID,    amount Money,    createdAt time.Time,) Transfer {    return Transfer{        id:                   ID,        accountOriginID:      accountOriginID,        accountDestinationID: accountDestinationID,        amount:               amount,        createdAt:            createdAt,    }}func (t Transfer) ID() TransferID {    return t.id}func (t Transfer) AccountOriginID() AccountID {    return t.accountOriginID}func (t Transfer) AccountDestinationID() AccountID {    return t.accountDestinationID}func (t Transfer) Amount() Money {    return t.amount}func (t Transfer) CreatedAt() time.Time {    return t.createdAt}
transfer定义了TransferRepository接口及Transfer类型

usecase

➜  usecase git:(master) tree.├── create_account.go├── create_account_test.go├── create_transfer.go├── create_transfer_test.go├── find_account_balance.go├── find_account_balance_test.go├── find_all_account.go├── find_all_account_test.go├── find_all_transfer.go└── find_all_transfer_test.go

这一层定义了CreateAccountUseCase与CreateAccountPresenter、CreateTransferUseCase与CreateTransferPresenter、FindAccountBalanceUseCase与FindAccountBalancePresenter、FindAllAccountUseCase与FindAllAccountPresenter、FindAllTransferUseCase与FindAllTransferPresenter接口

adapter

➜  adapter git:(master) tree.├── api│   ├── action│   │   ├── create_account.go│   │   ├── create_account_test.go│   │   ├── create_transfer.go│   │   ├── create_transfer_test.go│   │   ├── find_account_balance.go│   │   ├── find_account_balance_test.go│   │   ├── find_all_account.go│   │   ├── find_all_account_test.go│   │   ├── find_all_transfer.go│   │   ├── find_all_transfer_test.go│   │   ├── health_check.go│   │   └── health_check_test.go│   ├── logging│   │   ├── error.go│   │   └── info.go│   ├── middleware│   │   └── logger.go│   └── response│       ├── error.go│       └── success.go├── logger│   └── logger.go├── presenter│   ├── create_account.go│   ├── create_account_test.go│   ├── create_transfer.go│   ├── create_transfer_test.go│   ├── find_account_balance.go│   ├── find_account_balance_test.go│   ├── find_all_account.go│   ├── find_all_account_test.go│   ├── find_all_transfer.go│   └── find_all_transfer_test.go├── repository│   ├── account_mongodb.go│   ├── account_postgres.go│   ├── nosql.go│   ├── sql.go│   ├── transfer_mongodb.go│   └── transfer_postgres.go└── validator    └── validator.go
adapter层实现了domain与usecase层定义的接口

小结

go-bank-transfer工程在domain层定义了model及repository接口,usecase层定义了usecase及presenter接口,同时调用domain层实现业务编排;adapter则实现了下面两层定义的接口。

doc

  • go-bank-transfer