序
本文次要赏析一下 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 string
func (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 string
func (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